[
  {
    "path": ".dockerignore",
    "content": "# Ignore node_modules\nnode_modules\n\n# Ignore logs\n*.log\nlogs\n*.log.*\n\n# Ignore environment variables\n.env\n\n# Ignore build directories and files\ndist\nbuild\n\n# Ignore temporary files and directories\ntmp\ntemp\n*.tmp\n*.swp\n*.swo\n*.bak\n\n# Ignore Docker-related files\nDockerfile*\ndocker-compose.yml\n\n# Ignore IDE/editor specific files\n.vscode\n.idea\n*.iml\n*.sublime-project\n*.sublime-workspace\n\n# Ignore OS-specific files\n.DS_Store"
  },
  {
    "path": ".eslintrc.cjs",
    "content": "module.exports = {\n  root: true,\n  env: { browser: true, es2020: true },\n  extends: [\n    \"eslint:recommended\",\n    \"plugin:react/recommended\",\n    \"plugin:react/jsx-runtime\",\n    \"plugin:react-hooks/recommended\",\n    \"prettier\",\n  ],\n  ignorePatterns: [\"dist\", \".eslintrc.cjs\"],\n  parserOptions: { ecmaVersion: \"latest\", sourceType: \"module\" },\n  settings: { react: { version: \"18.2\" } },\n  plugins: [\"react-refresh\"],\n  rules: {\n    \"react-refresh/only-export-components\": [\n      \"warn\",\n      { allowConstantExport: true },\n    ],\n    \"react/prop-types\": 0,\n    \"react-refresh/only-export-components\": \"off\",\n  },\n};\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: 1ilit\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"[BUG]\"\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Desktop (please complete the following information):**\n - OS: [e.g. iOS]\n - Browser [e.g. chrome, safari]\n\n**Additional context**\nAdd any other context about the problem here. If the bug involves the import feature, please, attach the  imported file.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: \"[FEATURE]\"\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build\n\non:\n  push:\n    branches: [ \"main\" ]\n  pull_request:\n    branches: [ \"main\" ]\n    types: [ opened, synchronize, reopened ]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: [18.x, 20.x]\n\n    steps:\n    - uses: actions/checkout@v3\n    - name: Use Node.js ${{ matrix.node-version }}\n      uses: actions/setup-node@v3\n      with:\n        node-version: ${{ matrix.node-version }}\n        cache: 'npm'\n    - run: npm install\n    - name: Run eslint \n      run: npm run lint\n    - name: Run vite build\n      run: npm run build\n"
  },
  {
    "path": ".github/workflows/docker.yml",
    "content": "name: Docker Build and Push\n\non:\n  push:\n    tags:\n      - \"*\"\n\nconcurrency:\n  group: \"docker-image\"\n  cancel-in-progress: false\n\njobs:\n  docker:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n\n    - name: Set up QEMU\n      uses: docker/setup-qemu-action@v3\n\n    - name: Set up Docker Buildx\n      uses: docker/setup-buildx-action@v3\n\n\n    - name: Log in to ghcr\n      uses: docker/login-action@v3\n      with:\n        registry: ghcr.io\n        username: ${{ github.actor }}\n        password: ${{ secrets.GH_TOKEN }}\n    \n    - name: Build and push\n      uses: docker/build-push-action@v6\n      with:\n        push: true\n        tags: ghcr.io/${{ github.repository }}:latest,ghcr.io/${{ github.repository }}:${{ github.ref_name }}\n        platforms: linux/amd64,linux/arm64\n\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n.env\n"
  },
  {
    "path": ".prettierrc.json",
    "content": "{\n  \"singleQuote\": false,\n  \"arrowParens\": \"always\",\n  \"trailingComma\": \"all\",\n  \"tabWidth\": 2,\n  \"semi\": true\n}\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to drawDB\n\nThanks for taking the time to contribute!\n\nThe following is a set of guidelines for contributing to our project. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.\n\n## Table of Contents\n\n1. [How Can I Contribute?](#how-can-i-contribute)\n    - [Reporting Bugs](#reporting-bugs)\n    - [Suggesting Enhancements](#suggesting-enhancements)\n    - [Submitting Pull Requests](#submitting-pull-requests)\n2. [Style Guides](#style-guides)\n    - [Git Commit Messages](#git-commit-messages)\n    - [Style Guide](#style-guide)\n3. [Additional Notes](#additional-notes)\n    - [Issue and Pull Request Labels](#issue-and-pull-request-labels)\n    - [Getting Help](#getting-help)\n\n## How Can I Contribute?\n\n### Reporting Bugs\n\nThis section guides you through submitting a bug report for our project. Following these guidelines helps maintainers and the community understand your report, reproduce the behavior, and find related reports.\n\n- Use a clear and descriptive title for the issue to identify the problem.\n- Describe the exact steps which reproduce the problem in as many details as possible.\n- Provide specific examples to demonstrate the steps (e.g. if you're having trouble importing a file please attach it or provide a link to it).\n- Include screenshots if applicable.\n- Explain which behavior you expected to see instead and why.\n\n### Suggesting Enhancements\n\nThis section guides you through submitting an enhancement suggestion for our project, including completely new features and minor improvements to existing functionality.\n\n- Use a clear and descriptive title for the issue to identify the suggestion.\n- Explain why this enhancement would be useful to most users.\n\n### Submitting Pull Requests\n\nIf you would like to implement a big feature that has not been discussed before please reach out to the maintainer on Discord at @dottle_ or send an email to drawdb@outlook.com.\n\nPlease follow these steps to have your contribution considered by the maintainers:\n\n1. Make sure the pull request you work on is atomic. That is, it implements a single feature or fixes a single bug.\n2. Fork the repository and create your branch from `main`.\n3. Write clear, descriptive commit messages.\n4. Ensure your code adheres to the project's style guides.\n5. Create a pull request.\n6. Make sure to explain what your pull request solves unless it fixes something already explained in an issue that it's linked to.\n7. Explain the solution. If you implement a more involved feature explain the design decisions.\n\n## Style Guides\n\n### Git Commit Messages\n\n- Use the present tense (e.g. \"Add Spanish locale\" not \"Added Spanish locale\").\n- Use the imperative mood (e.g. \"Move cursor to...\" not \"Moves cursor to...\").\n- Reference issues and pull requests liberally after the first line.\n\n### Style Guide\n\n- Format your code with Prettier.\n- Ensure your code passes ESLint.\n- Make sure the code base is in English, this includes comments and variable names.\n\n## Additional Notes\n\n### Issue and Pull Request Labels\n\nThis section lists the labels we use to help organize and identify issues and pull requests.\n\n- `bug`: Something isn't working.\n- `enhancement`: New feature or request.\n- `question`: Further information is requested.\n- `documentation`: Improvements or additions to documentation.\n- `good first issue`: Good for newcomers.\n- `help wanted`: Extra attention is needed.\n\n### Getting Help\n\nIf you have any questions, please feel free to reach out to us through the following channels:\n\n- [Discord](https://discord.gg/BrjZgNrmR6)\n- [Email](drawdb@outlook.com)\n\n---\n\nThank you for your contributions! ❤️\n"
  },
  {
    "path": "Dockerfile",
    "content": "# Stage 1: Build the app\nFROM node:20-alpine AS build\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nENV NODE_OPTIONS=\"--max-old-space-size=4096\"\nRUN npm run build\n\n# Stage 2: Setup the Nginx Server to serve the app\nFROM docker.io/library/nginx:stable-alpine3.17 AS production\nCOPY --from=build /app/dist /usr/share/nginx/html\nRUN echo 'server { listen 80; server_name _; root /usr/share/nginx/html;  location / { try_files $uri /index.html; } }' > /etc/nginx/conf.d/default.conf\nEXPOSE 80\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\n  A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\n  The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\n  An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Remote Network Interaction; Use with the GNU General Public License.\n\n  Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as published\n    by the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source.  For example, if your program is a web application, its\ninterface could display a \"Source\" link that leads users to an archive\nof the code.  There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n<https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n  <sup>Special thanks to:</sup>\n  <br>\n  <a href=\"https://www.warp.dev/drawdb/\" target=\"_blank\">\n    <img alt=\"Warp sponsorship\" width=\"280\" src=\"https://github.com/user-attachments/assets/c7f141e7-9751-407d-bb0e-d6f2c487b34f\">\n    <br>\n    <b>Next-gen AI-powered intelligent terminal for all platforms</b>\n  </a>\n</div>\n\n<br/>\n<br/>\n\n<div align=\"center\">\n    <img width=\"64\" alt=\"drawdb logo\" src=\"./src/assets/icon-dark.png\">\n    <h1>drawDB</h1>\n</div>\n\n<h3 align=\"center\">Free, simple, and intuitive database schema editor and SQL generator.</h3>\n\n<div align=\"center\" style=\"margin-bottom:12px;\">\n    <a href=\"https://drawdb.app/\" style=\"display: flex; align-items: center;\">\n        <img src=\"https://img.shields.io/badge/Start%20building-grey\" alt=\"drawDB\"/>\n    </a>\n    <a href=\"https://discord.gg/BrjZgNrmR6\" style=\"display: flex; align-items: center;\">\n        <img src=\"https://img.shields.io/discord/1196658537208758412.svg?label=Join%20the%20Discord&logo=discord\" alt=\"Discord\"/>\n    </a>\n    <a href=\"https://x.com/drawDB_\" style=\"display: flex; align-items: center;\">\n        <img src=\"https://img.shields.io/badge/Follow%20us%20on%20X-blue?logo=X\" alt=\"Follow us on X\"/>\n    </a>\n    <a href=\"https://getmanta.ai/drawdb\">\n        <img src=\"https://getmanta.ai/api/badges?text=Manta%20Graph&link=drawdb\" alt=\"DrawDB graph on Manta\">\n    </a> \n</div>\n\n<h3 align=\"center\"><img width=\"700\" style=\"border-radius:5px;\" alt=\"demo\" src=\"drawdb.png\"></h3>\n\nDrawDB is a robust and user-friendly database entity relationship (DBER) editor right in your browser. Build diagrams with a few clicks, export sql scripts, customize your editor, and more without creating an account. See the full set of features [here](https://drawdb.app/).\n\n## Getting Started\n\n### Local Development\n\n```bash\ngit clone https://github.com/drawdb-io/drawdb\ncd drawdb\nnpm install\nnpm run dev\n```\n\n### Build\n\n```bash\ngit clone https://github.com/drawdb-io/drawdb\ncd drawdb\nnpm install\nnpm run build\n```\n\n### Docker Build\n\n```bash\ndocker build -t drawdb .\ndocker run -p 3000:80 drawdb\n```\n\nIf you want to enable sharing, set up the [server](https://github.com/drawdb-io/drawdb-server) and environment variables according to `.env.sample`. This is optional unless you need to share files..\n"
  },
  {
    "path": "compose.yml",
    "content": "services:\n  drawdb:\n    image: node:20-alpine\n    container_name: drawdb\n    ports:\n      - 5173:5173\n    working_dir: /var/www/html\n    volumes:\n      - ./:/var/www/html\n    command: sh -c \"npm install && npm run dev -- --host\"\n    networks:\n      - default\n\nnetworks:\n  default:\n    driver: bridge\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"/favicon.ico\" />\n\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n    <meta\n      name=\"description\"\n      content=\"Online database entity-realtionship diagram editor, data modeler, and SQL generator. Design, visualize, and export scripts without an account and completely free of charge.\"\n    />\n\n    <meta name=\"robots\" content=\"index,follow,max-image-preview:large\" />\n\n    <meta property=\"og:type\" content=\"website\" />\n    <meta property=\"og:url\" content=\"https://drawdb.app/\" />\n    <meta\n      property=\"og:title\"\n      content=\"drawDB | Online database diagram editor and SQL generator\"\n    />\n    <meta\n      property=\"og:description\"\n      content=\"Online database entity-realtionship diagram editor, data modeler, and SQL generator. Design, visualize, and export scripts without an account and completely free of charge.\"\n    />\n    <meta property=\"og:image\" content=\"https://drawdb.app/hero_ss.png\" />\n\n    <meta\n      name=\"twitter:image:src\"\n      content=\"https://drawdb.app/hero_ss.png\"\n    />\n    <meta\n      name=\"twitter:tile:image\"\n      content=\"https://drawdb.app/hero_ss.png\"\n    />\n    <meta name=\"twitter:card\" content=\"summary_large_image\" />\n\n    <link rel=\"apple-touch-icon\" href=\"/favicon.ico\" />\n    <link\n      rel=\"stylesheet\"\n      href=\"https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css\"\n      crossorigin=\"anonymous\"\n    />\n\n    <link\n      rel=\"stylesheet\"\n      href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css\"\n      integrity=\"sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==\"\n      crossorigin=\"anonymous\"\n      referrerpolicy=\"no-referrer\"\n    />\n\n    <title>drawDB | Online database diagram editor and SQL generator</title>\n  </head>\n  <body theme-mode=\"light\">\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.jsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"drawdb\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"lint\": \"eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@dbml/core\": \"^3.13.9\",\n    \"@dnd-kit/core\": \"^6.3.1\",\n    \"@dnd-kit/sortable\": \"^10.0.0\",\n    \"@dnd-kit/utilities\": \"^3.2.2\",\n    \"@douyinfe/semi-ui\": \"^2.77.1\",\n    \"@lexical/react\": \"^0.12.5\",\n    \"@monaco-editor/react\": \"^4.7.0\",\n    \"@vercel/analytics\": \"^1.2.2\",\n    \"axios\": \"^1.13.5\",\n    \"dexie\": \"^3.2.4\",\n    \"dexie-react-hooks\": \"^1.1.7\",\n    \"file-saver\": \"^2.0.5\",\n    \"framer-motion\": \"^10.18.0\",\n    \"html-to-image\": \"1.11.11\",\n    \"i18next\": \"^23.11.4\",\n    \"i18next-browser-languagedetector\": \"^8.0.0\",\n    \"jsonschema\": \"^1.4.1\",\n    \"jspdf\": \"^4.2.1\",\n    \"jszip\": \"^3.10.1\",\n    \"lexical\": \"^0.12.5\",\n    \"lodash\": \"^4.17.23\",\n    \"luxon\": \"^3.7.1\",\n    \"nanoid\": \"^5.1.5\",\n    \"node-sql-parser\": \"^5.4.0\",\n    \"oracle-sql-parser\": \"^0.1.0\",\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"react-hotkeys-hook\": \"^4.4.1\",\n    \"react-i18next\": \"^14.1.1\",\n    \"react-router-dom\": \"^6.30.3\",\n    \"react-tweet\": \"^3.2.1\",\n    \"usehooks-ts\": \"^3.1.0\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/postcss\": \"^4.0.14\",\n    \"@types/react\": \"^18.2.43\",\n    \"@types/react-dom\": \"^18.2.17\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"eslint\": \"^8.55.0\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"eslint-plugin-react\": \"^7.33.2\",\n    \"eslint-plugin-react-hooks\": \"^4.6.0\",\n    \"eslint-plugin-react-refresh\": \"^0.4.5\",\n    \"postcss\": \"^8.4.32\",\n    \"prettier\": \"3.2.5\",\n    \"tailwindcss\": \"^4.0.14\",\n    \"vite\": \"^6.4.1\"\n  }\n}\n"
  },
  {
    "path": "postcss.config.js",
    "content": "export default {\n  plugins: {\n    '@tailwindcss/postcss': {},\n  },\n}\n"
  },
  {
    "path": "public/robots.txt",
    "content": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nAllow: /\nAllow: /editor\nAllow: /templates\nDisallow: /bug-report\n"
  },
  {
    "path": "src/App.jsx",
    "content": "import { BrowserRouter, Routes, Route, useLocation } from \"react-router-dom\";\nimport { useLayoutEffect } from \"react\";\nimport Editor from \"./pages/Editor\";\nimport BugReport from \"./pages/BugReport\";\nimport Templates from \"./pages/Templates\";\nimport LandingPage from \"./pages/LandingPage\";\nimport SettingsContextProvider from \"./context/SettingsContext\";\nimport NotFound from \"./pages/NotFound\";\n\nexport default function App() {\n  return (\n    <SettingsContextProvider>\n      <BrowserRouter>\n        <RestoreScroll />\n        <Routes>\n          <Route path=\"/\" element={<LandingPage />} />\n          <Route path=\"/editor\" element={<Editor />} />\n          <Route path=\"/editor/diagrams/:id\" element={<Editor />} />\n          <Route path=\"/editor/templates/:id\" element={<Editor />} />\n          <Route path=\"/bug-report\" element={<BugReport />} />\n          <Route path=\"/templates\" element={<Templates />} />\n          <Route path=\"*\" element={<NotFound />} />\n        </Routes>\n      </BrowserRouter>\n    </SettingsContextProvider>\n  );\n}\n\nfunction RestoreScroll() {\n  const location = useLocation();\n  useLayoutEffect(() => {\n    window.scroll(0, 0);\n  }, [location.pathname]);\n  return null;\n}\n"
  },
  {
    "path": "src/animations/FadeIn.jsx",
    "content": "import { useRef, useEffect } from \"react\";\nimport { motion, useInView, useAnimation } from \"framer-motion\";\n\nexport default function FadeIn({ children, duration }) {\n  const ref = useRef(null);\n  const isInView = useInView(ref, { once: true });\n  const mainControls = useAnimation();\n\n  useEffect(() => {\n    if (isInView) {\n      mainControls.start(\"visible\");\n    }\n  }, [isInView, mainControls]);\n\n  return (\n    <div ref={ref}>\n      <motion.div\n        variants={{\n          hidden: { opacity: 0 },\n          visible: { opacity: 1 },\n        }}\n        initial=\"hidden\"\n        animate={mainControls}\n        transition={{ duration }}\n      >\n        {children}\n      </motion.div>\n    </div>\n  );\n}"
  },
  {
    "path": "src/animations/SlideIn.jsx",
    "content": "import { useRef, useEffect } from \"react\";\nimport { motion, useInView, useAnimation } from \"framer-motion\";\n\nexport default function SlideIn({ children, duration, delay, className }) {\n  const ref = useRef(null);\n  const isInView = useInView(ref, { once: true });\n  const mainControls = useAnimation();\n\n  useEffect(() => {\n    if (isInView) {\n      mainControls.start(\"visible\");\n    }\n  }, [isInView, mainControls]);\n\n  return (\n    <div ref={ref} className={className}>\n      <motion.div\n        variants={{\n          hidden: { opacity: 0, x: -60 },\n          visible: { opacity: 1, x: 0 },\n        }}\n        initial=\"hidden\"\n        animate={mainControls}\n        transition={{ duration, delay }}\n        className=\"h-full\"\n      >\n        {children}\n      </motion.div>\n    </div>\n  );\n}"
  },
  {
    "path": "src/api/email.js",
    "content": "import axios from \"axios\";\n\nexport async function send(subject, message, attachments) {\n  return await axios.post(`${import.meta.env.VITE_BACKEND_URL}/email/send`, {\n    subject,\n    message,\n    attachments,\n  });\n}\n"
  },
  {
    "path": "src/api/gists.js",
    "content": "import axios from \"axios\";\n\nexport const SHARE_FILENAME = \"share.json\";\nexport const VERSION_FILENAME = \"versionned.json\";\n\nconst description = \"drawDB diagram\";\nconst baseUrl = import.meta.env.VITE_BACKEND_URL;\n\nexport async function create(filename, content) {\n  const res = await axios.post(`${baseUrl}/gists`, {\n    public: false,\n    filename,\n    description,\n    content,\n  });\n\n  return res.data.data.id;\n}\n\nexport async function patch(gistId, filename, content) {\n  const { data } = await axios.patch(`${baseUrl}/gists/${gistId}`, {\n    filename,\n    content,\n  });\n\n  return data.deleted;\n}\n\nexport async function del(gistId) {\n  await axios.delete(`${baseUrl}/gists/${gistId}`);\n}\n\nexport async function get(gistId) {\n  const res = await axios.get(`${baseUrl}/gists/${gistId}`);\n\n  return res.data;\n}\n\nexport async function getCommits(gistId, perPage = 20, page = 1) {\n  const res = await axios.get(`${baseUrl}/gists/${gistId}/commits`, {\n    params: {\n      per_page: perPage,\n      page,\n    },\n  });\n\n  return res.data;\n}\n\nexport async function getVersion(gistId, sha) {\n  const res = await axios.get(`${baseUrl}/gists/${gistId}/${sha}`);\n\n  return res.data;\n}\n\nexport async function getCommitsWithFile(\n  gistId,\n  file,\n  limit = 10,\n  cursor = null,\n) {\n  const res = await axios.get(\n    `${baseUrl}/gists/${gistId}/file-versions/${file}`,\n    {\n      params: {\n        limit,\n        cursor,\n      },\n    },\n  );\n\n  return res.data;\n}\n\nexport async function compare(gistId, file, versionA, versionB) {\n  const res = await axios.get(\n    `${baseUrl}/gists/${gistId}/file/${file}/compare/${versionA}/${versionB}`,\n  );\n\n  return res.data;\n}\n"
  },
  {
    "path": "src/components/CodeEditor/index.jsx",
    "content": "import { useState } from \"react\";\nimport { Editor } from \"@monaco-editor/react\";\nimport { useDiagram, useSettings } from \"../../hooks\";\nimport { Button } from \"@douyinfe/semi-ui\";\nimport { useTranslation } from \"react-i18next\";\nimport { IconCopy, IconTick } from \"@douyinfe/semi-icons\";\nimport { setUpDBML } from \"./setUpDBML\";\n\nexport default function CodeEditor({\n  showCopyButton,\n  extraControls,\n  filename,\n  className = \"\",\n  ...props\n}) {\n  const { settings } = useSettings();\n  const { database } = useDiagram();\n  const { t } = useTranslation();\n  const [copied, setCopied] = useState(false);\n\n  const copyCode = () => {\n    navigator.clipboard\n      .writeText(props.value)\n      .then(() => {\n        setCopied(true);\n        setTimeout(() => setCopied(false), 3000);\n      })\n      .catch((e) => console.error(e));\n  };\n\n  const handleEditorMount = (editor, monaco) => {\n    setUpDBML(monaco, database);\n    setTimeout(() => {\n      editor.getAction(\"editor.action.formatDocument\").run();\n    }, 300);\n  };\n\n  return (\n    <div className={`relative h-full ${className}`}>\n      {filename && (\n        <div\n          className={`px-4 py-2 rounded-t-md text-xs flex justify-between items-center ${\n            settings.mode === \"dark\"\n              ? \"bg-neutral-800 text-gray-50\"\n              : \"bg-gray-100 text-gray-800\"\n          }`}\n        >\n          <div>{filename}</div>\n          <button\n            onClick={copyCode}\n            className=\"flex items-center gap-1 hover:opacity-80\"\n          >\n            <i className={`bi ${copied ? \"bi-check2\" : \"bi-copy\"} me-1`} />\n            {t(\"copy\")}\n          </button>\n        </div>\n      )}\n      <Editor\n        {...props}\n        theme={settings.mode === \"light\" ? \"vs\" : \"vs-dark\"}\n        onMount={handleEditorMount}\n      />\n      {showCopyButton && (\n        <div className=\"absolute flex flex-col right-6 bottom-2 z-10 space-y-2\">\n          {extraControls}\n          <Button\n            icon={copied ? <IconTick /> : <IconCopy />}\n            onClick={copyCode}\n            className=\"inline-block\"\n          />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CodeEditor/setUpDBML.js",
    "content": "import { dbToTypes } from \"../../data/datatypes\";\n\nexport function setUpDBML(monaco, database) {\n  monaco.languages.register({ id: \"dbml\" });\n\n  monaco.languages.setMonarchTokensProvider(\"dbml\", {\n    defaultToken: \"\",\n    tokenPostfix: \".dbml\",\n    ignoreCase: true,\n\n    keywords: [\n      \"table\",\n      \"tablegroup\",\n      \"project\",\n      \"enum\",\n      \"ref\",\n      \"as\",\n      \"indexes\",\n      \"index\",\n      \"note\",\n      \"delete\",\n      \"update\",\n      \"pk\",\n      \"increment\",\n      \"not\",\n      \"null\",\n      \"unique\",\n      \"default\",\n    ],\n\n    typeKeywords: Object.keys(dbToTypes[database]),\n\n    operators: [\n      \"=\",\n      \">\",\n      \"<\",\n      \"!\",\n      \"~\",\n      \"?\",\n      \":\",\n      \"==\",\n      \"<=\",\n      \">=\",\n      \"!=\",\n      \"&&\",\n      \"||\",\n      \"++\",\n      \"--\",\n      \"+\",\n      \"-\",\n      \"*\",\n      \"/\",\n      \"&\",\n      \"|\",\n      \"^\",\n    ],\n\n    symbols: /[=><!~?:&|+\\-*/^%]+/,\n    escapes:\n      /\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,\n\n    tokenizer: {\n      root: [\n        [\n          /[a-zA-Z_$][\\w$]*/,\n          {\n            cases: {\n              \"@keywords\": \"keyword\",\n              \"@typeKeywords\": \"type\",\n              \"@default\": \"identifier\",\n            },\n          },\n        ],\n        { include: \"@whitespace\" },\n        [/[{}()[\\]]/, \"@brackets\"],\n        [/[<>](?!@symbols)/, \"@brackets\"],\n        [\n          /@symbols/,\n          {\n            cases: {\n              \"@operators\": \"operator\",\n              \"@default\": \"\",\n            },\n          },\n        ],\n        [/\\d*\\.\\d+([eE][-+]?\\d+)?/, \"number.float\"],\n        [/0[xX][0-9a-fA-F]+/, \"number.hex\"],\n        [/\\d+/, \"number\"],\n        [/[;,.]/, \"delimiter\"],\n        [/\"([^\"\\\\]|\\\\.)*$/, \"string.invalid\"],\n        [/'([^'\\\\]|\\\\.)*$/, \"string.invalid\"],\n        [/\"/, { token: \"string.quote\", bracket: \"@open\", next: \"@dqstring\" }],\n        [/'/, { token: \"string.quote\", bracket: \"@open\", next: \"@sqstring\" }],\n      ],\n\n      dqstring: [\n        [/[^\\\\\"]+/, \"string\"],\n        [/@escapes/, \"string.escape\"],\n        [/\\\\./, \"string.escape.invalid\"],\n        [/\"/, { token: \"string.quote\", bracket: \"@close\", next: \"@pop\" }],\n      ],\n\n      sqstring: [\n        [/[^\\\\']+/, \"string\"],\n        [/@escapes/, \"string.escape\"],\n        [/\\\\./, \"string.escape.invalid\"],\n        [/'/, { token: \"string.quote\", bracket: \"@close\", next: \"@pop\" }],\n      ],\n\n      comment: [\n        [/[^\\\\/*]+/, \"comment\"],\n        [/\\/\\*/, \"comment\", \"@push\"],\n        [\"\\\\*/\", \"comment\", \"@pop\"],\n        [/[\\\\/*]/, \"comment\"],\n      ],\n\n      whitespace: [\n        [/[ \\t\\r\\n]+/, \"white\"],\n        [/\\/\\*/, \"comment\", \"@comment\"],\n        [/\\/\\/.*$/, \"comment\"],\n      ],\n    },\n  });\n\n  monaco.languages.setLanguageConfiguration(\"dbml\", {\n    comments: {\n      lineComment: \"//\",\n      blockComment: [\"/*\", \"*/\"],\n    },\n    brackets: [\n      [\"{\", \"}\"],\n      [\"[\", \"]\"],\n      [\"(\", \")\"],\n    ],\n    autoClosingPairs: [\n      { open: \"{\", close: \"}\" },\n      { open: \"[\", close: \"]\" },\n      { open: \"(\", close: \")\" },\n      { open: '\"', close: '\"' },\n      { open: \"'\", close: \"'\" },\n    ],\n    surroundingPairs: [\n      { open: \"{\", close: \"}\" },\n      { open: \"[\", close: \"]\" },\n      { open: \"(\", close: \")\" },\n      { open: '\"', close: '\"' },\n      { open: \"'\", close: \"'\" },\n    ],\n  });\n}\n"
  },
  {
    "path": "src/components/EditorCanvas/Area.jsx",
    "content": "import { useMemo, useRef, useState } from \"react\";\nimport { Button, Popover, Input } from \"@douyinfe/semi-ui\";\nimport ColorPicker from \"../EditorSidePanel/ColorPicker\";\nimport {\n  IconEdit,\n  IconDeleteStroked,\n  IconLock,\n  IconUnlock,\n} from \"@douyinfe/semi-icons\";\nimport { Tab, Action, ObjectType, State } from \"../../data/constants\";\nimport {\n  useLayout,\n  useSettings,\n  useUndoRedo,\n  useSelect,\n  useAreas,\n  useSaveState,\n} from \"../../hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport { useHover } from \"usehooks-ts\";\n\nexport default function Area({\n  data,\n  onPointerDown,\n  setResize,\n  setInitDimensions,\n}) {\n  const ref = useRef(null);\n  const isHovered = useHover(ref);\n  const { layout } = useLayout();\n  const { settings } = useSettings();\n  const { setSaveState } = useSaveState();\n  const { updateArea } = useAreas();\n  const {\n    selectedElement,\n    setSelectedElement,\n    bulkSelectedElements,\n    setBulkSelectedElements,\n  } = useSelect();\n\n  const handleResize = (e, dir) => {\n    setResize({ id: data.id, dir: dir });\n    setInitDimensions({\n      x: data.x,\n      y: data.y,\n      width: data.width,\n      height: data.height,\n    });\n  };\n\n  const lockUnlockArea = (e) => {\n    const locking = !data.locked;\n    updateArea(data.id, { locked: locking });\n\n    const lockArea = () => {\n      setSelectedElement({\n        ...selectedElement,\n        element: ObjectType.NONE,\n        id: -1,\n        open: false,\n      });\n      setBulkSelectedElements((prev) =>\n        prev.filter((el) => el.id !== data.id || el.type !== ObjectType.AREA),\n      );\n    };\n\n    const unlockArea = () => {\n      const elementInBulk = {\n        id: data.id,\n        type: ObjectType.AREA,\n        initialCoords: { x: data.x, y: data.y },\n        currentCoords: { x: data.x, y: data.y },\n      };\n      if (e.ctrlKey || e.metaKey) {\n        setBulkSelectedElements((prev) => [...prev, elementInBulk]);\n      } else {\n        setBulkSelectedElements([elementInBulk]);\n      }\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: ObjectType.AREA,\n        id: data.id,\n        open: false,\n      }));\n    };\n\n    if (locking) {\n      lockArea();\n    } else {\n      unlockArea();\n    }\n  };\n\n  const edit = () => {\n    if (layout.sidebar) {\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: ObjectType.AREA,\n        id: data.id,\n        currentTab: Tab.AREAS,\n        open: true,\n      }));\n      if (selectedElement.currentTab !== Tab.AREAS) return;\n      document\n        .getElementById(`scroll_area_${data.id}`)\n        .scrollIntoView({ behavior: \"smooth\" });\n    } else {\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: ObjectType.AREA,\n        id: data.id,\n        open: true,\n      }));\n    }\n  };\n\n  const onClickOutSide = () => {\n    if (selectedElement.editFromToolbar) {\n      setSelectedElement((prev) => ({\n        ...prev,\n        editFromToolbar: false,\n      }));\n      return;\n    }\n    setSelectedElement((prev) => ({\n      ...prev,\n      open: false,\n    }));\n    setSaveState(State.SAVING);\n  };\n\n  const areaIsOpen = () =>\n    selectedElement.element === ObjectType.AREA &&\n    selectedElement.id === data.id &&\n    selectedElement.open;\n\n  const isSelected = useMemo(() => {\n    return (\n      (selectedElement.id === data.id &&\n        selectedElement.element === ObjectType.AREA) ||\n      bulkSelectedElements.some(\n        (e) => e.type === ObjectType.AREA && e.id === data.id,\n      )\n    );\n  }, [selectedElement, data, bulkSelectedElements]);\n\n  return (\n    <g ref={ref}>\n      <foreignObject\n        key={data.id}\n        x={data.x}\n        y={data.y}\n        width={data.width > 0 ? data.width : 0}\n        height={data.height > 0 ? data.height : 0}\n        onPointerDown={onPointerDown}\n      >\n        <div\n          className={`w-full h-full p-2 rounded cursor-move border-2 ${\n            isHovered\n              ? \"border-dashed border-blue-500\"\n              : isSelected\n                ? \"border-blue-500 opacity-100\"\n                : \"border-slate-400 opacity-100\"\n          }`}\n          style={{ backgroundColor: `${data.color}66` }}\n          onDoubleClick={edit}\n        >\n          <div className=\"flex justify-between gap-1 w-full\">\n            <div className=\"text-color select-none overflow-hidden text-ellipsis\">\n              {data.name}\n            </div>\n            {(isHovered || (areaIsOpen() && !layout.sidebar)) && (\n              <div className=\"flex items-center gap-1.5\">\n                <Button\n                  icon={data.locked ? <IconLock /> : <IconUnlock />}\n                  size=\"small\"\n                  theme=\"solid\"\n                  style={{\n                    backgroundColor: \"#2F68ADB3\",\n                  }}\n                  onClick={lockUnlockArea}\n                  disabled={layout.readOnly}\n                />\n                <Popover\n                  visible={areaIsOpen() && !layout.sidebar}\n                  onClickOutSide={onClickOutSide}\n                  stopPropagation\n                  content={<EditPopoverContent data={data} />}\n                  trigger=\"custom\"\n                  position=\"rightTop\"\n                  showArrow\n                >\n                  <Button\n                    icon={<IconEdit />}\n                    size=\"small\"\n                    theme=\"solid\"\n                    style={{\n                      backgroundColor: \"#2F68ADB3\",\n                    }}\n                    onClick={edit}\n                  />\n                </Popover>\n              </div>\n            )}\n          </div>\n        </div>\n      </foreignObject>\n      {isHovered && (\n        <>\n          <circle\n            cx={data.x}\n            cy={data.y}\n            r={6}\n            fill={settings.mode === \"light\" ? \"white\" : \"rgb(28, 31, 35)\"}\n            stroke=\"#5891db\"\n            strokeWidth={2}\n            cursor=\"nwse-resize\"\n            onPointerDown={(e) => e.isPrimary && handleResize(e, \"tl\")}\n          />\n          <circle\n            cx={data.x + data.width}\n            cy={data.y}\n            r={6}\n            fill={settings.mode === \"light\" ? \"white\" : \"rgb(28, 31, 35)\"}\n            stroke=\"#5891db\"\n            strokeWidth={2}\n            cursor=\"nesw-resize\"\n            onPointerDown={(e) => e.isPrimary && handleResize(e, \"tr\")}\n          />\n          <circle\n            cx={data.x}\n            cy={data.y + data.height}\n            r={6}\n            fill={settings.mode === \"light\" ? \"white\" : \"rgb(28, 31, 35)\"}\n            stroke=\"#5891db\"\n            strokeWidth={2}\n            cursor=\"nesw-resize\"\n            onPointerDown={(e) => e.isPrimary && handleResize(e, \"bl\")}\n          />\n          <circle\n            cx={data.x + data.width}\n            cy={data.y + data.height}\n            r={6}\n            fill={settings.mode === \"light\" ? \"white\" : \"rgb(28, 31, 35)\"}\n            stroke=\"#5891db\"\n            strokeWidth={2}\n            cursor=\"nwse-resize\"\n            onPointerDown={(e) => e.isPrimary && handleResize(e, \"br\")}\n          />\n        </>\n      )}\n    </g>\n  );\n}\n\nfunction EditPopoverContent({ data }) {\n  const [editField, setEditField] = useState({});\n  const { updateArea, deleteArea } = useAreas();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const { t } = useTranslation();\n  const { layout } = useLayout();\n  const initialColorRef = useRef(data.color);\n\n  const handleColorPick = (color) => {\n    setUndoStack((prev) => {\n      let undoColor = initialColorRef.current;\n      const lastColorChange = prev.findLast(\n        (e) =>\n          e.element === ObjectType.AREA &&\n          e.aid === data.id &&\n          e.action === Action.EDIT &&\n          e.redo?.color,\n      );\n      if (lastColorChange) {\n        undoColor = lastColorChange.redo.color;\n      }\n\n      if (color === undoColor) return prev;\n\n      const newStack = [\n        ...prev,\n        {\n          action: Action.EDIT,\n          element: ObjectType.AREA,\n          aid: data.id,\n          undo: { color: undoColor },\n          redo: { color: color },\n          message: t(\"edit_area\", {\n            areaName: data.name,\n            extra: \"[color]\",\n          }),\n        },\n      ];\n      return newStack;\n    });\n    setRedoStack([]);\n  };\n\n  return (\n    <div className=\"popover-theme\">\n      <div className=\"font-semibold mb-2 ms-1\">{t(\"edit\")}</div>\n      <div className=\"w-[280px] flex items-center mb-2\">\n        <Input\n          value={data.name}\n          placeholder={t(\"name\")}\n          className=\"me-2\"\n          readonly={layout.readOnly}\n          onChange={(value) => updateArea(data.id, { name: value })}\n          onFocus={(e) => setEditField({ name: e.target.value })}\n          onBlur={(e) => {\n            if (e.target.value === editField.name) return;\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.AREA,\n                aid: data.id,\n                undo: editField,\n                redo: { name: e.target.value },\n                message: t(\"edit_area\", {\n                  areaName: e.target.value,\n                  extra: \"[name]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n          }}\n        />\n        <ColorPicker\n          usePopover={true}\n          readOnly={layout.readOnly}\n          value={data.color}\n          onChange={(color) => updateArea(data.id, { color })}\n          onColorPick={(color) => handleColorPick(color)}\n        />\n      </div>\n      <div className=\"flex\">\n        <Button\n          icon={<IconDeleteStroked />}\n          type=\"danger\"\n          block\n          onClick={() => deleteArea(data.id, true)}\n          disabled={layout.readOnly}\n        >\n          {t(\"delete\")}\n        </Button>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorCanvas/Canvas.jsx",
    "content": "import { useRef, useState } from \"react\";\nimport {\n  Action,\n  Cardinality,\n  Constraint,\n  darkBgTheme,\n  ObjectType,\n  gridSize,\n  gridCircleRadius,\n  minAreaSize,\n} from \"../../data/constants\";\nimport { Toast } from \"@douyinfe/semi-ui\";\nimport Table from \"./Table\";\nimport Area from \"./Area\";\nimport Relationship from \"./Relationship\";\nimport Note from \"./Note\";\nimport {\n  useCanvas,\n  useSettings,\n  useTransform,\n  useDiagram,\n  useUndoRedo,\n  useSelect,\n  useAreas,\n  useNotes,\n  useLayout,\n  useSaveState,\n} from \"../../hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport { useEventListener } from \"usehooks-ts\";\nimport { areFieldsCompatible, getTableHeight } from \"../../utils/utils\";\nimport { getRectFromEndpoints, isInsideRect } from \"../../utils/rect\";\nimport { State, noteWidth } from \"../../data/constants\";\nimport { nanoid } from \"nanoid\";\n\nexport default function Canvas() {\n  const { t } = useTranslation();\n\n  const canvasRef = useRef(null);\n  const canvasContextValue = useCanvas();\n  const {\n    canvas: { viewBox },\n    pointer,\n  } = canvasContextValue;\n\n  const { tables, updateTable, relationships, addRelationship, database } =\n    useDiagram();\n  const { setSaveState } = useSaveState();\n  const { areas, updateArea } = useAreas();\n  const { notes, updateNote } = useNotes();\n  const { layout } = useLayout();\n  const { settings } = useSettings();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const { transform, setTransform } = useTransform();\n  const {\n    selectedElement,\n    setSelectedElement,\n    bulkSelectedElements,\n    setBulkSelectedElements,\n  } = useSelect();\n  const notDragging = {\n    id: -1,\n    type: ObjectType.NONE,\n    grabOffset: { x: 0, y: 0 },\n  };\n  const [dragging, setDragging] = useState(notDragging);\n  const [linking, setLinking] = useState(false);\n  const [linkingLine, setLinkingLine] = useState({\n    startTableId: -1,\n    startFieldId: -1,\n    endTableId: -1,\n    endFieldId: -1,\n    startX: 0,\n    startY: 0,\n    endX: 0,\n    endY: 0,\n  });\n  const [hoveredTable, setHoveredTable] = useState({\n    tableId: null,\n    fieldId: null,\n  });\n  const [panning, setPanning] = useState({\n    isPanning: false,\n    panStart: { x: 0, y: 0 },\n    cursorStart: { x: 0, y: 0 },\n  });\n  const [areaResize, setAreaResize] = useState({ id: -1, dir: \"none\" });\n  const [areaInitDimensions, setAreaInitDimensions] = useState({\n    x: 0,\n    y: 0,\n    width: 0,\n    height: 0,\n  });\n  const [bulkSelectRect, setBulkSelectRect] = useState({\n    x1: 0,\n    y1: 0,\n    x2: 0,\n    y2: 0,\n    show: false,\n    ctrlKey: false,\n    metaKey: false,\n  });\n  // this is used to store the element that is clicked on\n  // at the moment, and shouldn't be a part of the state\n  let elementPointerDown = null;\n\n  const isSameElement = (el1, el2) => {\n    return el1.id === el2.id && el1.type === el2.type;\n  };\n\n  const collectSelectedElements = () => {\n    const rect = getRectFromEndpoints(bulkSelectRect);\n    const elements = [];\n    const shouldAddElement = (elementRect, element) => {\n      // if ctrl key is pressed, only add the elements that are not already selected\n      // can theoretically be optimized later if the selected elements is\n      // a map from id to element (after the ids are made unique)\n      return (\n        isInsideRect(elementRect, rect) &&\n        ((!bulkSelectRect.ctrlKey && !bulkSelectRect.metaKey) ||\n          !bulkSelectedElements.some((el) => isSameElement(el, element)))\n      );\n    };\n\n    tables.forEach((table) => {\n      if (table.locked) return;\n\n      const element = {\n        id: table.id,\n        type: ObjectType.TABLE,\n        currentCoords: { x: table.x, y: table.y },\n        initialCoords: { x: table.x, y: table.y },\n      };\n      const tableRect = {\n        x: table.x,\n        y: table.y,\n        width: settings.tableWidth,\n        height: getTableHeight(\n          table,\n          settings.tableWidth,\n          settings.showComments,\n        ),\n      };\n      if (shouldAddElement(tableRect, element)) {\n        elements.push(element);\n      }\n    });\n\n    areas.forEach((area) => {\n      if (area.locked) return;\n\n      const element = {\n        id: area.id,\n        type: ObjectType.AREA,\n        currentCoords: { x: area.x, y: area.y },\n        initialCoords: { x: area.x, y: area.y },\n      };\n      const areaRect = {\n        x: area.x,\n        y: area.y,\n        width: area.width,\n        height: area.height,\n      };\n      if (shouldAddElement(areaRect, element)) {\n        elements.push(element);\n      }\n    });\n\n    notes.forEach((note) => {\n      if (note.locked) return;\n\n      const element = {\n        id: note.id,\n        type: ObjectType.NOTE,\n        currentCoords: { x: note.x, y: note.y },\n        initialCoords: { x: note.x, y: note.y },\n      };\n      const noteRect = {\n        x: note.x,\n        y: note.y,\n        width: note.width ?? noteWidth,\n        height: note.height,\n      };\n      if (shouldAddElement(noteRect, element)) {\n        elements.push(element);\n      }\n    });\n\n    if (bulkSelectRect.ctrlKey || bulkSelectRect.metaKey) {\n      setBulkSelectedElements([...bulkSelectedElements, ...elements]);\n    } else {\n      setBulkSelectedElements(elements);\n    }\n  };\n\n  const handlePointerDownOnElement = (e, { element, type }) => {\n    if (selectedElement.open && !layout.sidebar) return;\n\n    if (!e.isPrimary) return;\n\n    if (!element.locked || !(e.ctrlKey || e.metaKey)) {\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: type,\n        id: element.id,\n        open: false,\n      }));\n    }\n\n    if (element.locked) {\n      if (!(e.ctrlKey || e.metaKey)) {\n        setBulkSelectedElements([]);\n      }\n      return;\n    }\n\n    setBulkSelectRect((prev) => ({\n      ...prev,\n      show: false,\n    }));\n\n    // this is the object that will be added to the bulk selected elements\n    // if necessary\n    const elementInBulk = {\n      id: element.id,\n      type,\n      currentCoords: { x: element.x, y: element.y },\n      initialCoords: { x: element.x, y: element.y },\n    };\n\n    const isSelected = bulkSelectedElements.some((el) =>\n      isSameElement(el, elementInBulk),\n    );\n\n    if (e.ctrlKey || e.metaKey) {\n      if (isSelected) {\n        if (bulkSelectedElements.length > 1) {\n          setBulkSelectedElements(\n            bulkSelectedElements.filter(\n              (el) => !isSameElement(el, elementInBulk),\n            ),\n          );\n          setSelectedElement({\n            ...selectedElement,\n            element: ObjectType.NONE,\n            id: -1,\n            open: false,\n          });\n        }\n      } else {\n        setBulkSelectedElements([...bulkSelectedElements, elementInBulk]);\n      }\n      setDragging(notDragging);\n      return;\n    }\n\n    if (!isSelected) {\n      setBulkSelectedElements([elementInBulk]);\n    }\n    setDragging({\n      id: element.id,\n      type,\n      grabOffset: {\n        x: pointer.spaces.diagram.x - element.x,\n        y: pointer.spaces.diagram.y - element.y,\n      },\n    });\n  };\n\n  const coordinatesAfterSnappingToGrid = ({ x, y }) => {\n    if (settings.snapToGrid) {\n      return {\n        x: Math.round(x / gridSize) * gridSize,\n        y: Math.round(y / gridSize) * gridSize,\n      };\n    }\n    return { x, y };\n  };\n\n  /**\n   * @param {PointerEvent} e\n   */\n  const handlePointerMove = (e) => {\n    if (selectedElement.open && !layout.sidebar) return;\n\n    if (!e.isPrimary) return;\n\n    if (panning.isPanning) {\n      setTransform((prev) => ({\n        ...prev,\n        pan: {\n          x:\n            panning.panStart.x +\n            (panning.cursorStart.x - pointer.spaces.screen.x) / transform.zoom,\n          y:\n            panning.panStart.y +\n            (panning.cursorStart.y - pointer.spaces.screen.y) / transform.zoom,\n        },\n      }));\n      return;\n    }\n\n    if (layout.readOnly) return;\n\n    if (linking) {\n      setLinkingLine({\n        ...linkingLine,\n        endX: pointer.spaces.diagram.x,\n        endY: pointer.spaces.diagram.y,\n      });\n      return;\n    }\n\n    if (isDragging()) {\n      const { x: mainElementFinalX, y: mainElementFinalY } =\n        coordinatesAfterSnappingToGrid({\n          x: pointer.spaces.diagram.x - dragging.grabOffset.x,\n          y: pointer.spaces.diagram.y - dragging.grabOffset.y,\n        });\n\n      const { currentCoords } = bulkSelectedElements.find((el) =>\n        isSameElement(el, dragging),\n      );\n\n      const deltaX = mainElementFinalX - currentCoords.x;\n      const deltaY = mainElementFinalY - currentCoords.y;\n\n      const newBulkSelectedElements = [];\n      bulkSelectedElements.forEach((el) => {\n        const elementFinalCoords = {\n          x: el.currentCoords.x + deltaX,\n          y: el.currentCoords.y + deltaY,\n        };\n        if (el.type === ObjectType.TABLE) {\n          updateTable(el.id, { ...elementFinalCoords });\n        }\n        if (el.type === ObjectType.AREA) {\n          updateArea(el.id, { ...elementFinalCoords });\n        }\n        if (el.type === ObjectType.NOTE) {\n          updateNote(el.id, { ...elementFinalCoords });\n        }\n        newBulkSelectedElements.push({\n          ...el,\n          currentCoords: elementFinalCoords,\n        });\n      });\n\n      setBulkSelectedElements(newBulkSelectedElements);\n      return;\n    }\n\n    if (areaResize.id !== -1) {\n      if (areaResize.dir === \"none\") return;\n      let newDims = { ...areaInitDimensions };\n      setPanning((old) => ({ ...old, isPanning: false }));\n      const { x, y } = coordinatesAfterSnappingToGrid(pointer.spaces.diagram);\n\n      switch (areaResize.dir) {\n        case \"br\":\n          newDims.width = x - areaInitDimensions.x;\n          newDims.height = y - areaInitDimensions.y;\n          break;\n        case \"tl\":\n          newDims.x = x;\n          newDims.y = y;\n          newDims.width = areaInitDimensions.width - (x - areaInitDimensions.x);\n          newDims.height =\n            areaInitDimensions.height - (y - areaInitDimensions.y);\n          break;\n        case \"tr\":\n          newDims.y = y;\n          newDims.width = x - areaInitDimensions.x;\n          newDims.height =\n            areaInitDimensions.height - (y - areaInitDimensions.y);\n          break;\n        case \"bl\":\n          newDims.x = x;\n          newDims.width = areaInitDimensions.width - (x - areaInitDimensions.x);\n          newDims.height = y - areaInitDimensions.y;\n          break;\n      }\n\n      if (newDims.width <= minAreaSize) {\n        newDims.width = minAreaSize;\n        if (areaResize.dir === \"tl\" || areaResize.dir === \"bl\") {\n          newDims.x =\n            areaInitDimensions.x + areaInitDimensions.width - minAreaSize;\n        }\n      }\n\n      if (newDims.height <= minAreaSize) {\n        newDims.height = minAreaSize;\n        if (areaResize.dir === \"tl\" || areaResize.dir === \"tr\") {\n          newDims.y =\n            areaInitDimensions.y + areaInitDimensions.height - minAreaSize;\n        }\n      }\n\n      updateArea(areaResize.id, { ...newDims });\n      return;\n    }\n\n    if (bulkSelectRect.show) {\n      setBulkSelectRect((prev) => ({\n        ...prev,\n        x2: pointer.spaces.diagram.x,\n        y2: pointer.spaces.diagram.y,\n      }));\n    }\n  };\n\n  /**\n   * @param {PointerEvent} e\n   */\n  const handlePointerDown = (e) => {\n    if (!e.isPrimary) return;\n\n    // don't pan if the sidesheet for editing a table is open\n    if (\n      selectedElement.element === ObjectType.TABLE &&\n      selectedElement.open &&\n      !layout.sidebar\n    )\n      return;\n\n    const isMouseLeftButton = e.button === 0;\n    const isMouseMiddleButton = e.button === 1;\n\n    if (isMouseLeftButton) {\n      setBulkSelectRect({\n        x1: pointer.spaces.diagram.x,\n        y1: pointer.spaces.diagram.y,\n        x2: pointer.spaces.diagram.x,\n        y2: pointer.spaces.diagram.y,\n        show: elementPointerDown === null || !elementPointerDown.element.locked,\n        ctrlKey: e.ctrlKey,\n        metaKey: e.metaKey,\n      });\n      if (elementPointerDown !== null) {\n        handlePointerDownOnElement(e, elementPointerDown);\n      }\n      pointer.setStyle(\"crosshair\");\n    } else if (isMouseMiddleButton) {\n      setPanning({\n        isPanning: true,\n        panStart: transform.pan,\n        // Diagram space depends on the current panning.\n        // Use screen space to avoid circular dependencies and undefined behavior.\n        cursorStart: pointer.spaces.screen,\n      });\n      pointer.setStyle(\"grabbing\");\n    }\n  };\n\n  const isDragging = () => {\n    return dragging.type !== ObjectType.NONE && dragging.id !== -1;\n  };\n\n  const didDrag = () => {\n    if (!isDragging()) return false;\n    // checking any element is sufficient\n    const { currentCoords, initialCoords } = bulkSelectedElements[0];\n    return (\n      currentCoords.x !== initialCoords.x || currentCoords.y !== initialCoords.y\n    );\n  };\n\n  const didResize = (id) => {\n    return !(\n      areas[id].x === areaInitDimensions.x &&\n      areas[id].y === areaInitDimensions.y &&\n      areas[id].width === areaInitDimensions.width &&\n      areas[id].height === areaInitDimensions.height\n    );\n  };\n\n  const didPan = () =>\n    !(\n      transform.pan.x === panning.panStart.x &&\n      transform.pan.y === panning.panStart.y\n    );\n\n  /**\n   * @param {PointerEvent} e\n   */\n  const handlePointerUp = (e) => {\n    if (selectedElement.open && !layout.sidebar) return;\n\n    if (!e.isPrimary) return;\n\n    if (didDrag()) {\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.MOVE,\n          bulk: true,\n          message: t(\"bulk_update\"),\n          elements: bulkSelectedElements.map((el) => ({\n            id: el.id,\n            type: el.type,\n            undo: el.initialCoords,\n            redo: el.currentCoords,\n          })),\n        },\n      ]);\n      setRedoStack([]);\n      setBulkSelectedElements((prev) =>\n        prev.map((el) => ({\n          ...el,\n          initialCoords: { ...el.currentCoords },\n        })),\n      );\n    }\n\n    if (bulkSelectRect.show) {\n      setBulkSelectRect((prev) => ({\n        ...prev,\n        x2: pointer.spaces.diagram.x,\n        y2: pointer.spaces.diagram.y,\n        show: false,\n      }));\n      if (!isDragging()) {\n        collectSelectedElements();\n      }\n    }\n    setDragging(notDragging);\n\n    if (panning.isPanning && didPan()) {\n      setSaveState(State.SAVING);\n    }\n    setPanning((old) => ({ ...old, isPanning: false }));\n    pointer.setStyle(\"default\");\n\n    if (linking) handleLinking();\n    setLinking(false);\n\n    if (areaResize.id !== -1 && didResize(areaResize.id)) {\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.EDIT,\n          element: ObjectType.AREA,\n          aid: areaResize.id,\n          undo: {\n            ...areas[areaResize.id],\n            x: areaInitDimensions.x,\n            y: areaInitDimensions.y,\n            width: areaInitDimensions.width,\n            height: areaInitDimensions.height,\n          },\n          redo: areas[areaResize.id],\n          message: t(\"edit_area\", {\n            areaName: areas[areaResize.id].name,\n            extra: \"[resize]\",\n          }),\n        },\n      ]);\n      setRedoStack([]);\n    }\n    setAreaResize({ id: -1, dir: \"none\" });\n    setAreaInitDimensions({\n      x: 0,\n      y: 0,\n      width: 0,\n      height: 0,\n    });\n  };\n\n  const handleGripField = () => {\n    setPanning((old) => ({ ...old, isPanning: false }));\n    setDragging(notDragging);\n    setLinking(true);\n  };\n\n  const getCardinality = (startField, endField) => {\n    const startIsUnique = startField.unique || startField.primary;\n    const endIsUnique = endField.unique || endField.primary;\n\n    if (startIsUnique && endIsUnique) {\n      return Cardinality.ONE_TO_ONE;\n    }\n\n    if (startIsUnique && !endIsUnique) {\n      return Cardinality.ONE_TO_MANY;\n    }\n\n    if (!startIsUnique && endIsUnique) {\n      return Cardinality.MANY_TO_ONE;\n    }\n\n    return Cardinality.ONE_TO_ONE;\n  };\n\n  const handleLinking = () => {\n    if (hoveredTable.tableId === null) return;\n    if (hoveredTable.fieldId === null) return;\n\n    const { fields: startTableFields, name: startTableName } = tables.find(\n      (t) => t.id === linkingLine.startTableId,\n    );\n    const startField = startTableFields.find(\n      (f) => f.id === linkingLine.startFieldId,\n    );\n    const { fields: endTableFields, name: endTableName } = tables.find(\n      (t) => t.id === hoveredTable.tableId,\n    );\n    const endField = endTableFields.find((f) => f.id === hoveredTable.fieldId);\n\n    if (!areFieldsCompatible(database, startField.type, endField.type)) {\n      Toast.info(t(\"cannot_connect\"));\n      return;\n    }\n    if (\n      linkingLine.startTableId === hoveredTable.tableId &&\n      linkingLine.startFieldId === hoveredTable.fieldId\n    )\n      return;\n\n    const cardinality = getCardinality(startField, endField);\n\n    const newRelationship = {\n      ...linkingLine,\n      cardinality,\n      endTableId: hoveredTable.tableId,\n      endFieldId: hoveredTable.fieldId,\n      updateConstraint: Constraint.NONE,\n      deleteConstraint: Constraint.NONE,\n      name: `fk_${startTableName}_${startField.name}_${endTableName}`,\n      id: nanoid(),\n    };\n    delete newRelationship.startX;\n    delete newRelationship.startY;\n    delete newRelationship.endX;\n    delete newRelationship.endY;\n    addRelationship(newRelationship);\n  };\n\n  useEventListener(\n    \"wheel\",\n    (e) => {\n      e.preventDefault();\n\n      if (e.ctrlKey || e.metaKey) {\n        // How \"eager\" the viewport is to\n        // center the cursor's coordinates\n        const eagernessFactor = 0.05;\n        setTransform((prev) => ({\n          pan: {\n            x:\n              prev.pan.x -\n              (pointer.spaces.diagram.x - prev.pan.x) *\n                eagernessFactor *\n                Math.sign(e.deltaY),\n            y:\n              prev.pan.y -\n              (pointer.spaces.diagram.y - prev.pan.y) *\n                eagernessFactor *\n                Math.sign(e.deltaY),\n          },\n          zoom: e.deltaY <= 0 ? prev.zoom * 1.05 : prev.zoom / 1.05,\n        }));\n      } else if (e.shiftKey) {\n        setTransform((prev) => ({\n          ...prev,\n          pan: {\n            ...prev.pan,\n            x: prev.pan.x + e.deltaY / prev.zoom,\n          },\n        }));\n      } else {\n        setTransform((prev) => ({\n          ...prev,\n          pan: {\n            x: prev.pan.x + e.deltaX / prev.zoom,\n            y: prev.pan.y + e.deltaY / prev.zoom,\n          },\n        }));\n      }\n    },\n    canvasRef,\n    { passive: false },\n  );\n\n  return (\n    <div className=\"grow h-full touch-none\" id=\"canvas\">\n      <div\n        className=\"w-full h-full\"\n        style={{\n          cursor: pointer.style,\n          backgroundColor: settings.mode === \"dark\" ? darkBgTheme : \"white\",\n        }}\n      >\n        <svg\n          id=\"diagram\"\n          ref={canvasRef}\n          onPointerMove={handlePointerMove}\n          onPointerDown={handlePointerDown}\n          onPointerUp={handlePointerUp}\n          className=\"absolute w-full h-full touch-none\"\n          viewBox={`${viewBox.left} ${viewBox.top} ${viewBox.width} ${viewBox.height}`}\n        >\n          {settings.showGrid && (\n            <>\n              <defs>\n                <pattern\n                  id=\"pattern-grid\"\n                  x={-gridCircleRadius}\n                  y={-gridCircleRadius}\n                  width={gridSize}\n                  height={gridSize}\n                  patternUnits=\"userSpaceOnUse\"\n                  patternContentUnits=\"userSpaceOnUse\"\n                >\n                  <circle\n                    cx={gridCircleRadius}\n                    cy={gridCircleRadius}\n                    r={gridCircleRadius}\n                    fill=\"rgb(99, 152, 191)\"\n                    opacity=\"1\"\n                  />\n                </pattern>\n              </defs>\n              <rect\n                x={viewBox.left}\n                y={viewBox.top}\n                width={viewBox.width}\n                height={viewBox.height}\n                fill=\"url(#pattern-grid)\"\n              />\n            </>\n          )}\n          {areas.map((a) => (\n            <Area\n              key={a.id}\n              data={a}\n              setResize={setAreaResize}\n              setInitDimensions={setAreaInitDimensions}\n              onPointerDown={() => {\n                elementPointerDown = {\n                  element: a,\n                  type: ObjectType.AREA,\n                };\n              }}\n            />\n          ))}\n          {relationships.map((e) => (\n            <Relationship key={e.id} data={e} />\n          ))}\n          {tables.map((table) => (\n            <Table\n              key={table.id}\n              tableData={table}\n              setHoveredTable={setHoveredTable}\n              handleGripField={handleGripField}\n              setLinkingLine={setLinkingLine}\n              onPointerDown={() => {\n                elementPointerDown = {\n                  element: table,\n                  type: ObjectType.TABLE,\n                };\n              }}\n            />\n          ))}\n          {linking && (\n            <path\n              d={`M ${linkingLine.startX} ${linkingLine.startY} L ${linkingLine.endX} ${linkingLine.endY}`}\n              stroke=\"red\"\n              strokeDasharray=\"8,8\"\n              className=\"pointer-events-none touch-none\"\n            />\n          )}\n          {notes.map((n) => (\n            <Note\n              key={n.id}\n              data={n}\n              onPointerDown={() => {\n                elementPointerDown = {\n                  element: n,\n                  type: ObjectType.NOTE,\n                };\n              }}\n            />\n          ))}\n          {bulkSelectRect.show && (\n            <rect\n              {...getRectFromEndpoints(bulkSelectRect)}\n              stroke=\"grey\"\n              fill=\"grey\"\n              fillOpacity={0.15}\n              strokeDasharray={10}\n            />\n          )}\n        </svg>\n      </div>\n      {settings.showDebugCoordinates && (\n        <div className=\"fixed flex flex-col flex-wrap gap-6 bg-[rgba(var(--semi-grey-1),var(--tw-bg-opacity))]/40 border border-color bottom-4 right-4 p-4 rounded-xl backdrop-blur-xs pointer-events-none select-none\">\n          <table className=\"table-auto grow\">\n            <thead>\n              <tr>\n                <th className=\"text-left\" colSpan={3}>\n                  {t(\"transform\")}\n                </th>\n              </tr>\n              <tr className=\"italic [&_th]:font-normal [&_th]:text-right\">\n                <th>pan x</th>\n                <th>pan y</th>\n                <th>scale</th>\n              </tr>\n            </thead>\n            <tbody className=\"[&_td]:text-right [&_td]:min-w-[8ch]\">\n              <tr>\n                <td>{transform.pan.x.toFixed(2)}</td>\n                <td>{transform.pan.y.toFixed(2)}</td>\n                <td>{transform.zoom.toFixed(4)}</td>\n              </tr>\n            </tbody>\n          </table>\n          <table className=\"table-auto grow [&_th]:text-left [&_th:not(:first-of-type)]:text-right [&_td:not(:first-of-type)]:text-right [&_td]:min-w-[8ch]\">\n            <thead>\n              <tr>\n                <th colSpan={4}>{t(\"viewbox\")}</th>\n              </tr>\n              <tr className=\"italic [&_th]:font-normal\">\n                <th>left</th>\n                <th>top</th>\n                <th>width</th>\n                <th>height</th>\n              </tr>\n            </thead>\n            <tbody>\n              <tr>\n                <td>{viewBox.left.toFixed(2)}</td>\n                <td>{viewBox.top.toFixed(2)}</td>\n                <td>{viewBox.width.toFixed(2)}</td>\n                <td>{viewBox.height.toFixed(2)}</td>\n              </tr>\n            </tbody>\n          </table>\n          <table className=\"table-auto grow [&_th]:text-left [&_th:not(:first-of-type)]:text-right [&_td:not(:first-of-type)]:text-right [&_td]:min-w-[8ch]\">\n            <thead>\n              <tr>\n                <th colSpan={3}>{t(\"cursor_coordinates\")}</th>\n              </tr>\n              <tr className=\"italic [&_th]:font-normal\">\n                <th>{t(\"coordinate_space\")}</th>\n                <th>x</th>\n                <th>y</th>\n              </tr>\n            </thead>\n            <tbody>\n              <tr>\n                <td>{t(\"coordinate_space_screen\")}</td>\n                <td>{pointer.spaces.screen.x.toFixed(2)}</td>\n                <td>{pointer.spaces.screen.y.toFixed(2)}</td>\n              </tr>\n              <tr>\n                <td>{t(\"coordinate_space_diagram\")}</td>\n                <td>{pointer.spaces.diagram.x.toFixed(2)}</td>\n                <td>{pointer.spaces.diagram.y.toFixed(2)}</td>\n              </tr>\n            </tbody>\n          </table>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorCanvas/Note.jsx",
    "content": "import { useMemo, useState, useRef, useEffect } from \"react\";\nimport { Action, ObjectType, Tab, State } from \"../../data/constants\";\nimport { Input, Button, Popover } from \"@douyinfe/semi-ui\";\nimport ColorPicker from \"../EditorSidePanel/ColorPicker\";\nimport {\n  IconEdit,\n  IconDeleteStroked,\n  IconLock,\n  IconUnlock,\n} from \"@douyinfe/semi-icons\";\nimport {\n  useLayout,\n  useUndoRedo,\n  useSelect,\n  useNotes,\n  useSaveState,\n  useTransform,\n  useSettings,\n} from \"../../hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport { noteWidth, noteRadius, noteFold } from \"../../data/constants\";\n\nexport default function Note({ data, onPointerDown }) {\n  const [editField, setEditField] = useState({});\n  const [hovered, setHovered] = useState(false);\n  const [resizing, setResizing] = useState(false);\n  const initialWidthRef = useRef(data.width ?? noteWidth);\n  const initialXRef = useRef(data.x);\n  const { layout } = useLayout();\n  const { t } = useTranslation();\n  const { setSaveState } = useSaveState();\n  const { updateNote, deleteNote } = useNotes();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const { transform } = useTransform();\n  const { settings } = useSettings();\n  const {\n    selectedElement,\n    setSelectedElement,\n    bulkSelectedElements,\n    setBulkSelectedElements,\n  } = useSelect();\n  const initialColorRef = useRef(data.color);\n\n  const handleColorPick = (color) => {\n    setUndoStack((prev) => {\n      let undoColor = initialColorRef.current;\n      const lastColorChange = prev.findLast(\n        (e) =>\n          e.element === ObjectType.NOTE &&\n          e.nid === data.id &&\n          e.action === Action.EDIT &&\n          e.redo?.color,\n      );\n      if (lastColorChange) {\n        undoColor = lastColorChange.redo.color;\n      }\n\n      if (color === undoColor) return prev;\n\n      const newStack = [\n        ...prev,\n        {\n          action: Action.EDIT,\n          element: ObjectType.NOTE,\n          nid: data.id,\n          undo: { color: undoColor },\n          redo: { color: color },\n          message: t(\"edit_note\", {\n            noteTitle: data.title,\n            extra: \"[color]\",\n          }),\n        },\n      ];\n      return newStack;\n    });\n    setRedoStack([]);\n  };\n\n  const handleChange = (e) => {\n    const textarea = document.getElementById(`note_${data.id}`);\n    if (!textarea) return;\n    textarea.style.height = \"0\";\n    textarea.style.height = textarea.scrollHeight + \"px\";\n    const newHeight = textarea.scrollHeight + 42;\n    const updates = { content: e.target.value };\n    if (newHeight !== data.height) {\n      updates.height = newHeight;\n    }\n    updateNote(data.id, updates);\n  };\n\n  const handleBlur = (e) => {\n    if (e.target.value === editField.content) return;\n    const textarea = document.getElementById(`note_${data.id}`);\n    textarea.style.height = \"0\";\n    textarea.style.height = textarea.scrollHeight + \"px\";\n    const newHeight = textarea.scrollHeight + 16 + 20 + 4;\n    setUndoStack((prev) => [\n      ...prev,\n      {\n        action: Action.EDIT,\n        element: ObjectType.NOTE,\n        nid: data.id,\n        undo: editField,\n        redo: { content: e.target.value, height: newHeight },\n        message: t(\"edit_note\", {\n          noteTitle: e.target.value,\n          extra: \"[content]\",\n        }),\n      },\n    ]);\n    setRedoStack([]);\n  };\n\n  const lockUnlockNote = (e) => {\n    const locking = !data.locked;\n    updateNote(data.id, { locked: locking });\n\n    const lockNote = () => {\n      setSelectedElement({\n        ...selectedElement,\n        element: ObjectType.NONE,\n        id: -1,\n        open: false,\n      });\n      setBulkSelectedElements((prev) =>\n        prev.filter((el) => el.id !== data.id || el.type !== ObjectType.NOTE),\n      );\n    };\n\n    const unlockNote = () => {\n      const elementInBulk = {\n        id: data.id,\n        type: ObjectType.NOTE,\n        initialCoords: { x: data.x, y: data.y },\n        currentCoords: { x: data.x, y: data.y },\n      };\n      if (e.ctrlKey || e.metaKey) {\n        setBulkSelectedElements((prev) => [...prev, elementInBulk]);\n      } else {\n        setBulkSelectedElements([elementInBulk]);\n      }\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: ObjectType.NOTE,\n        id: data.id,\n        open: false,\n      }));\n    };\n\n    if (locking) {\n      lockNote();\n    } else {\n      unlockNote();\n    }\n  };\n\n  const edit = () => {\n    setSelectedElement((prev) => ({\n      ...prev,\n      ...(layout.sidebar && { currentTab: Tab.NOTES }),\n      ...(!layout.sidebar && { element: ObjectType.NOTE }),\n      id: data.id,\n      open: true,\n    }));\n\n    if (layout.sidebar && selectedElement.currentTab === Tab.NOTES) {\n      document\n        .getElementById(`scroll_note_${data.id}`)\n        .scrollIntoView({ behavior: \"smooth\" });\n    }\n  };\n\n  const isSelected = useMemo(() => {\n    return (\n      (selectedElement.id === data.id &&\n        selectedElement.element === ObjectType.NOTE) ||\n      bulkSelectedElements.some(\n        (e) => e.type === ObjectType.NOTE && e.id === data.id,\n      )\n    );\n  }, [selectedElement, data, bulkSelectedElements]);\n\n  const width = data.width ?? noteWidth;\n  const MIN_NOTE_WIDTH = 120;\n\n  useEffect(() => {\n    const textarea = document.getElementById(`note_${data.id}`);\n    if (!textarea) return;\n\n    textarea.style.height = \"0\";\n    const scrollHeight = textarea.scrollHeight;\n    textarea.style.height = scrollHeight + \"px\";\n    const newHeight = scrollHeight + 42;\n\n    if (newHeight === data.height) return;\n\n    updateNote(data.id, { height: newHeight });\n  }, [data.id, data.height, updateNote]);\n\n  return (\n    <g\n      onPointerEnter={(e) => e.isPrimary && setHovered(true)}\n      onPointerLeave={(e) => e.isPrimary && setHovered(false)}\n      onPointerDown={(e) => {\n        // Required for onPointerLeave to trigger when a touch pointer leaves\n        // https://stackoverflow.com/a/70976017/1137077\n        e.target.releasePointerCapture(e.pointerId);\n      }}\n      onDoubleClick={edit}\n    >\n      <path\n        d={`M${data.x + noteFold} ${data.y} L${data.x + width - noteRadius} ${\n          data.y\n        } A${noteRadius} ${noteRadius} 0 0 1 ${data.x + width} ${data.y + noteRadius} L${data.x + width} ${\n          data.y + data.height - noteRadius\n        } A${noteRadius} ${noteRadius} 0 0 1 ${data.x + width - noteRadius} ${data.y + data.height} L${\n          data.x + noteRadius\n        } ${data.y + data.height} A${noteRadius} ${noteRadius} 0 0 1 ${data.x} ${\n          data.y + data.height - noteRadius\n        } L${data.x} ${data.y + noteFold}`}\n        fill={data.color}\n        stroke={\n          hovered\n            ? \"rgb(59 130 246)\"\n            : isSelected\n              ? \"rgb(59 130 246)\"\n              : \"rgb(168 162 158)\"\n        }\n        strokeDasharray={hovered ? 5 : 0}\n        strokeLinejoin=\"round\"\n        strokeWidth=\"2\"\n      />\n      <path\n        d={`M${data.x} ${data.y + noteFold} L${data.x + noteFold - noteRadius} ${\n          data.y + noteFold\n        } A${noteRadius} ${noteRadius} 0 0 0 ${data.x + noteFold} ${data.y + noteFold - noteRadius} L${\n          data.x + noteFold\n        } ${data.y} L${data.x} ${data.y + noteFold} Z`}\n        fill={data.color}\n        stroke={\n          hovered\n            ? \"rgb(59 130 246)\"\n            : isSelected\n              ? \"rgb(59 130 246)\"\n              : \"rgb(168 162 158)\"\n        }\n        strokeDasharray={hovered ? 5 : 0}\n        strokeLinejoin=\"round\"\n        strokeWidth=\"2\"\n      />\n\n      {!layout.readOnly && !data.locked && hovered && (\n        <g style={{ pointerEvents: \"none\" }}>\n          <circle\n            cx={data.x}\n            cy={data.y + data.height / 2}\n            r={6}\n            fill={settings.mode === \"light\" ? \"white\" : \"rgb(28, 31, 35)\"}\n            stroke=\"#5891db\"\n            strokeWidth={2}\n            opacity={1}\n          />\n          <circle\n            cx={data.x + width}\n            cy={data.y + data.height / 2}\n            r={6}\n            fill={settings.mode === \"light\" ? \"white\" : \"rgb(28, 31, 35)\"}\n            stroke=\"#5891db\"\n            strokeWidth={2}\n            opacity={1}\n          />\n        </g>\n      )}\n      {!layout.readOnly && !data.locked && (\n        <rect\n          x={data.x - 4}\n          y={data.y + 8}\n          width={8}\n          height={Math.max(0, data.height - 16)}\n          fill=\"transparent\"\n          stroke=\"transparent\"\n          style={{ cursor: \"ew-resize\" }}\n          onPointerDown={(e) => {\n            e.stopPropagation();\n            initialWidthRef.current = data.width ?? noteWidth;\n            initialXRef.current = data.x;\n            setResizing(true);\n            e.currentTarget.setPointerCapture?.(e.pointerId);\n          }}\n          onPointerMove={(e) => {\n            if (!resizing) return;\n            const delta = e.movementX / (transform?.zoom || 1);\n            const currentWidth = data.width ?? noteWidth;\n            let proposedWidth = currentWidth - delta;\n            let proposedX = data.x + delta;\n            if (proposedWidth < MIN_NOTE_WIDTH) {\n              const clampDelta = currentWidth - MIN_NOTE_WIDTH;\n              proposedWidth = MIN_NOTE_WIDTH;\n              proposedX = data.x + clampDelta;\n            }\n            if (proposedWidth !== data.width || proposedX !== data.x) {\n              updateNote(data.id, { width: proposedWidth, x: proposedX });\n            }\n          }}\n          onPointerUp={(e) => {\n            if (!resizing) return;\n            setResizing(false);\n            e.stopPropagation();\n            const finalWidth = data.width ?? noteWidth;\n            const finalX = data.x;\n            const startWidth = initialWidthRef.current;\n            const startX = initialXRef.current;\n            if (finalWidth !== startWidth || finalX !== startX) {\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.NOTE,\n                  nid: data.id,\n                  undo: { width: startWidth, x: startX },\n                  redo: { width: finalWidth, x: finalX },\n                  message: t(\"edit_note\", {\n                    noteTitle: data.title,\n                    extra: \"[width/x]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n            }\n          }}\n        />\n      )}\n\n      {!layout.readOnly && !data.locked && (\n        <rect\n          x={data.x + width - 4}\n          y={data.y + 8}\n          width={8}\n          height={Math.max(0, data.height - 16)}\n          fill=\"transparent\"\n          stroke=\"transparent\"\n          style={{ cursor: \"ew-resize\" }}\n          onPointerDown={(e) => {\n            e.stopPropagation();\n            initialWidthRef.current = data.width ?? noteWidth;\n            setResizing(true);\n            e.currentTarget.setPointerCapture?.(e.pointerId);\n          }}\n          onPointerMove={(e) => {\n            if (!resizing) return;\n            const delta = e.movementX / (transform?.zoom || 1);\n            const next = Math.max(\n              MIN_NOTE_WIDTH,\n              (data.width ?? noteWidth) + delta,\n            );\n            if (next !== data.width) {\n              updateNote(data.id, { width: next });\n            }\n          }}\n          onPointerUp={(e) => {\n            if (!resizing) return;\n            setResizing(false);\n            e.stopPropagation();\n            const finalWidth = data.width ?? noteWidth;\n            const startWidth = initialWidthRef.current;\n            if (finalWidth !== startWidth) {\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.NOTE,\n                  nid: data.id,\n                  undo: { width: startWidth },\n                  redo: { width: finalWidth },\n                  message: t(\"edit_note\", {\n                    noteTitle: data.title,\n                    extra: \"[width]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n            }\n          }}\n        />\n      )}\n      <foreignObject\n        x={data.x}\n        y={data.y}\n        width={width}\n        height={data.height}\n        onPointerDown={onPointerDown}\n      >\n        <div className=\"text-gray-900 select-none w-full h-full cursor-move px-3 py-2\">\n          <div className=\"flex justify-between gap-1 w-full\">\n            <label\n              htmlFor={`note_${data.id}`}\n              className=\"ms-5 overflow-hidden text-ellipsis\"\n            >\n              {data.title}\n            </label>\n            {(hovered ||\n              (selectedElement.element === ObjectType.NOTE &&\n                selectedElement.id === data.id &&\n                selectedElement.open &&\n                !layout.sidebar)) && (\n              <div className=\"flex items-center gap-1.5\">\n                <Button\n                  icon={data.locked ? <IconLock /> : <IconUnlock />}\n                  size=\"small\"\n                  theme=\"solid\"\n                  style={{\n                    backgroundColor: \"#2F68ADB3\",\n                  }}\n                  onClick={lockUnlockNote}\n                  disabled={layout.readOnly}\n                />\n                <Popover\n                  visible={\n                    selectedElement.element === ObjectType.NOTE &&\n                    selectedElement.id === data.id &&\n                    selectedElement.open &&\n                    !layout.sidebar\n                  }\n                  onClickOutSide={() => {\n                    if (selectedElement.editFromToolbar) {\n                      setSelectedElement((prev) => ({\n                        ...prev,\n                        editFromToolbar: false,\n                      }));\n                      return;\n                    }\n                    setSelectedElement((prev) => ({\n                      ...prev,\n                      open: false,\n                    }));\n                    setSaveState(State.SAVING);\n                  }}\n                  stopPropagation\n                  content={\n                    <div className=\"popover-theme\">\n                      <div className=\"font-semibold mb-2 ms-1\">{t(\"edit\")}</div>\n                      <div className=\"w-[280px] flex items-center mb-2\">\n                        <Input\n                          value={data.title}\n                          placeholder={t(\"title\")}\n                          className=\"me-2\"\n                          readonly={layout.readOnly}\n                          onChange={(value) =>\n                            updateNote(data.id, { title: value })\n                          }\n                          onFocus={(e) =>\n                            setEditField({ title: e.target.value })\n                          }\n                          onBlur={(e) => {\n                            if (e.target.value === editField.title) return;\n                            setUndoStack((prev) => [\n                              ...prev,\n                              {\n                                action: Action.EDIT,\n                                element: ObjectType.NOTE,\n                                nid: data.id,\n                                undo: editField,\n                                redo: { title: e.target.value },\n                                message: t(\"edit_note\", {\n                                  noteTitle: e.target.value,\n                                  extra: \"[title]\",\n                                }),\n                              },\n                            ]);\n                            setRedoStack([]);\n                          }}\n                        />\n                        <ColorPicker\n                          usePopover={true}\n                          readOnly={layout.readOnly}\n                          value={data.color}\n                          onChange={(color) => updateNote(data.id, { color })}\n                          onColorPick={(color) => handleColorPick(color)}\n                        />\n                      </div>\n                      <div className=\"flex\">\n                        <Button\n                          block\n                          type=\"danger\"\n                          disabled={layout.readOnly}\n                          icon={<IconDeleteStroked />}\n                          onClick={() => deleteNote(data.id, true)}\n                        >\n                          {t(\"delete\")}\n                        </Button>\n                      </div>\n                    </div>\n                  }\n                  trigger=\"custom\"\n                  position=\"rightTop\"\n                  showArrow\n                >\n                  <Button\n                    icon={<IconEdit />}\n                    size=\"small\"\n                    theme=\"solid\"\n                    style={{\n                      backgroundColor: \"#2F68ADB3\",\n                    }}\n                    onClick={edit}\n                  />\n                </Popover>\n              </div>\n            )}\n          </div>\n          <textarea\n            id={`note_${data.id}`}\n            readOnly={layout.readOnly}\n            value={data.content}\n            onChange={handleChange}\n            onFocus={(e) =>\n              setEditField({\n                content: e.target.value,\n                height: data.height,\n              })\n            }\n            onBlur={handleBlur}\n            className=\"w-full resize-none outline-hidden overflow-y-hidden border-none select-none\"\n            style={{ backgroundColor: data.color }}\n          />\n        </div>\n      </foreignObject>\n    </g>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorCanvas/Relationship.jsx",
    "content": "import { useMemo, useRef, useState, useEffect } from \"react\";\nimport { Cardinality, ObjectType, Tab } from \"../../data/constants\";\nimport { calcPath } from \"../../utils/calcPath\";\nimport { useDiagram, useSettings, useLayout, useSelect } from \"../../hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport { SideSheet } from \"@douyinfe/semi-ui\";\nimport RelationshipInfo from \"../EditorSidePanel/RelationshipsTab/RelationshipInfo\";\n\nconst labelFontSize = 16;\n\nexport default function Relationship({ data }) {\n  const { settings } = useSettings();\n  const { tables } = useDiagram();\n  const { layout } = useLayout();\n  const { selectedElement, setSelectedElement } = useSelect();\n  const { t } = useTranslation();\n\n  const pathValues = useMemo(() => {\n    const startTable = tables.find((t) => t.id === data.startTableId);\n    const endTable = tables.find((t) => t.id === data.endTableId);\n\n    if (!startTable || !endTable || startTable.hidden || endTable.hidden)\n      return null;\n\n    return {\n      startFieldIndex: startTable.fields.findIndex(\n        (f) => f.id === data.startFieldId,\n      ),\n      endFieldIndex: endTable.fields.findIndex((f) => f.id === data.endFieldId),\n      startTable: {\n        x: startTable.x,\n        y: startTable.y,\n        comment: startTable.comment,\n      },\n      endTable: { x: endTable.x, y: endTable.y, comment: endTable.comment },\n    };\n  }, [tables, data]);\n\n  const pathRef = useRef();\n  const labelRef = useRef();\n\n  let cardinalityStart = \"1\";\n  let cardinalityEnd = \"1\";\n\n  switch (data.cardinality) {\n    // the translated values are to ensure backwards compatibility\n    case t(Cardinality.MANY_TO_ONE):\n    case Cardinality.MANY_TO_ONE:\n      cardinalityStart = data.manyLabel || \"n\";\n      cardinalityEnd = \"1\";\n      break;\n    case t(Cardinality.ONE_TO_MANY):\n    case Cardinality.ONE_TO_MANY:\n      cardinalityStart = \"1\";\n      cardinalityEnd = data.manyLabel || \"n\";\n      break;\n    case t(Cardinality.ONE_TO_ONE):\n    case Cardinality.ONE_TO_ONE:\n      cardinalityStart = \"1\";\n      cardinalityEnd = \"1\";\n      break;\n    default:\n      break;\n  }\n\n  let cardinalityStartX = 0;\n  let cardinalityEndX = 0;\n  let cardinalityStartY = 0;\n  let cardinalityEndY = 0;\n  let labelX = 0;\n  let labelY = 0;\n\n  let labelWidth = labelRef.current?.getBBox().width ?? 0;\n  let labelHeight = labelRef.current?.getBBox().height ?? 0;\n\n  const cardinalityOffset = 28;\n\n  if (pathRef.current) {\n    const pathLength = pathRef.current.getTotalLength();\n\n    const labelPoint = pathRef.current.getPointAtLength(pathLength / 2);\n    labelX = labelPoint.x - (labelWidth ?? 0) / 2;\n    labelY = labelPoint.y + (labelHeight ?? 0) / 2;\n\n    const point1 = pathRef.current.getPointAtLength(cardinalityOffset);\n    cardinalityStartX = point1.x;\n    cardinalityStartY = point1.y;\n    const point2 = pathRef.current.getPointAtLength(\n      pathLength - cardinalityOffset,\n    );\n    cardinalityEndX = point2.x;\n    cardinalityEndY = point2.y;\n  }\n\n  const edit = () => {\n    if (!layout.sidebar) {\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: ObjectType.RELATIONSHIP,\n        id: data.id,\n        open: true,\n      }));\n    } else {\n      setSelectedElement((prev) => ({\n        ...prev,\n        currentTab: Tab.RELATIONSHIPS,\n        element: ObjectType.RELATIONSHIP,\n        id: data.id,\n        open: true,\n      }));\n      if (selectedElement.currentTab !== Tab.RELATIONSHIPS) return;\n      document\n        .getElementById(`scroll_ref_${data.id}`)\n        .scrollIntoView({ behavior: \"smooth\" });\n    }\n  };\n\n  if (!pathValues) return null;\n\n  return (\n    <>\n      <g className=\"select-none group\" onDoubleClick={edit}>\n        {/* invisible wider path for better hover ux */}\n        <path\n          d={calcPath(pathValues, settings.tableWidth, 1, settings.showComments)}\n          fill=\"none\"\n          stroke=\"transparent\"\n          strokeWidth={12}\n          cursor=\"pointer\"\n        />\n        <path\n          ref={pathRef}\n          d={calcPath(pathValues, settings.tableWidth, 1, settings.showComments)}\n          className=\"relationship-path\"\n          fill=\"none\"\n          cursor=\"pointer\"\n        />\n        {settings.showRelationshipLabels && (\n          <text\n            x={labelX}\n            y={labelY}\n            fill={settings.mode === \"dark\" ? \"lightgrey\" : \"#333\"}\n            fontSize={labelFontSize}\n            fontWeight={500}\n            ref={labelRef}\n            className=\"group-hover:fill-sky-600\"\n          >\n            {data.name}\n          </text>\n        )}\n        {pathRef.current && settings.showCardinality && (\n          <>\n            <CardinalityLabel\n              x={cardinalityStartX}\n              y={cardinalityStartY}\n              text={cardinalityStart}\n            />\n            <CardinalityLabel\n              x={cardinalityEndX}\n              y={cardinalityEndY}\n              text={cardinalityEnd}\n            />\n          </>\n        )}\n      </g>\n      <SideSheet\n        title={t(\"edit\")}\n        size=\"small\"\n        visible={\n          selectedElement.element === ObjectType.RELATIONSHIP &&\n          selectedElement.id === data.id &&\n          selectedElement.open &&\n          !layout.sidebar\n        }\n        onCancel={() => {\n          setSelectedElement((prev) => ({\n            ...prev,\n            open: false,\n          }));\n        }}\n        style={{ paddingBottom: \"16px\" }}\n      >\n        <div className=\"sidesheet-theme\">\n          <RelationshipInfo data={data} />\n        </div>\n      </SideSheet>\n    </>\n  );\n}\n\nfunction CardinalityLabel({ x, y, text, r = 12, padding = 14 }) {\n  const [textWidth, setTextWidth] = useState(0);\n  const textRef = useRef(null);\n\n  useEffect(() => {\n    if (textRef.current) {\n      const bbox = textRef.current.getBBox();\n      setTextWidth(bbox.width);\n    }\n  }, [text]);\n\n  return (\n    <g>\n      <rect\n        x={x - textWidth / 2 - padding / 2}\n        y={y - r}\n        rx={r}\n        ry={r}\n        width={textWidth + padding}\n        height={r * 2}\n        fill=\"grey\"\n        className=\"group-hover:fill-sky-600\"\n      />\n      <text\n        ref={textRef}\n        x={x}\n        y={y}\n        fill=\"white\"\n        strokeWidth=\"0.5\"\n        textAnchor=\"middle\"\n        alignmentBaseline=\"middle\"\n      >\n        {text}\n      </text>\n    </g>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorCanvas/Table.jsx",
    "content": "import { useMemo, useState } from \"react\";\nimport {\n  Tab,\n  ObjectType,\n  tableFieldHeight,\n  tableHeaderHeight,\n  tableColorStripHeight,\n} from \"../../data/constants\";\nimport {\n  IconEdit,\n  IconMore,\n  IconMinus,\n  IconDeleteStroked,\n  IconKeyStroked,\n  IconLock,\n  IconUnlock,\n} from \"@douyinfe/semi-icons\";\nimport { Popover, Tag, Button, SideSheet } from \"@douyinfe/semi-ui\";\nimport { useLayout, useSettings, useDiagram, useSelect } from \"../../hooks\";\nimport TableInfo from \"../EditorSidePanel/TablesTab/TableInfo\";\nimport { useTranslation } from \"react-i18next\";\nimport { dbToTypes } from \"../../data/datatypes\";\nimport { isRtl } from \"../../i18n/utils/rtl\";\nimport i18n from \"../../i18n/i18n\";\nimport { getCommentHeight, getTableHeight } from \"../../utils/utils\";\n\nexport default function Table({\n  tableData,\n  onPointerDown,\n  setHoveredTable,\n  handleGripField,\n  setLinkingLine,\n}) {\n  const [hoveredField, setHoveredField] = useState(null);\n  const { database } = useDiagram();\n  const { layout } = useLayout();\n  const { deleteTable, deleteField, updateTable } = useDiagram();\n  const { settings } = useSettings();\n  const { t } = useTranslation();\n  const {\n    selectedElement,\n    setSelectedElement,\n    bulkSelectedElements,\n    setBulkSelectedElements,\n  } = useSelect();\n\n  const borderColor = useMemo(\n    () => (settings.mode === \"light\" ? \"border-zinc-300\" : \"border-zinc-600\"),\n    [settings.mode],\n  );\n\n  const height = getTableHeight(\n    tableData,\n    settings.tableWidth,\n    settings.showComments,\n  );\n\n  const isSelected = useMemo(() => {\n    return (\n      (selectedElement.id == tableData.id &&\n        selectedElement.element === ObjectType.TABLE) ||\n      bulkSelectedElements.some(\n        (e) => e.type === ObjectType.TABLE && e.id === tableData.id,\n      )\n    );\n  }, [selectedElement, tableData, bulkSelectedElements]);\n\n  const lockUnlockTable = (e) => {\n    const locking = !tableData.locked;\n    updateTable(tableData.id, { locked: locking });\n\n    const lockTable = () => {\n      setSelectedElement({\n        ...selectedElement,\n        element: ObjectType.NONE,\n        id: -1,\n        open: false,\n      });\n      setBulkSelectedElements((prev) =>\n        prev.filter(\n          (el) => el.id !== tableData.id || el.type !== ObjectType.TABLE,\n        ),\n      );\n    };\n\n    const unlockTable = () => {\n      const elementInBulk = {\n        id: tableData.id,\n        type: ObjectType.TABLE,\n        initialCoords: { x: tableData.x, y: tableData.y },\n        currentCoords: { x: tableData.x, y: tableData.y },\n      };\n      if (e.ctrlKey || e.metaKey) {\n        setBulkSelectedElements((prev) => [...prev, elementInBulk]);\n      } else {\n        setBulkSelectedElements([elementInBulk]);\n      }\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: ObjectType.TABLE,\n        id: tableData.id,\n        open: false,\n      }));\n    };\n\n    if (locking) {\n      lockTable();\n    } else {\n      unlockTable();\n    }\n  };\n\n  const openEditor = () => {\n    if (!layout.sidebar) {\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: ObjectType.TABLE,\n        id: tableData.id,\n        open: true,\n      }));\n    } else {\n      setSelectedElement((prev) => ({\n        ...prev,\n        currentTab: Tab.TABLES,\n        element: ObjectType.TABLE,\n        id: tableData.id,\n        open: true,\n      }));\n      if (selectedElement.currentTab !== Tab.TABLES) return;\n      document\n        .getElementById(`scroll_table_${tableData.id}`)\n        .scrollIntoView({ behavior: \"smooth\" });\n    }\n  };\n\n  if (tableData.hidden) return null;\n\n  return (\n    <>\n      <foreignObject\n        key={tableData.id}\n        x={tableData.x}\n        y={tableData.y}\n        width={settings.tableWidth}\n        height={height}\n        className=\"group drop-shadow-lg rounded-md cursor-move\"\n        onPointerDown={onPointerDown}\n      >\n        <div\n          onDoubleClick={openEditor}\n          className={`border-2 hover:border-dashed hover:border-blue-500\n               select-none rounded-lg w-full ${\n                 settings.mode === \"light\"\n                   ? \"bg-zinc-100 text-zinc-800\"\n                   : \"bg-zinc-800 text-zinc-200\"\n               } ${isSelected ? \"border-solid border-blue-500\" : borderColor}`}\n          style={{ direction: \"ltr\" }}\n        >\n          <div\n            className=\"h-[10px] w-full rounded-t-md\"\n            style={{ backgroundColor: tableData.color }}\n          />\n          <div\n            className={`border-b border-gray-400 ${\n              settings.mode === \"light\" ? \"bg-zinc-200\" : \"bg-zinc-900\"\n            } ${tableData.comment && settings.showComments ? \"pb-3\" : \"\"}`}\n          >\n            <div\n              className={`overflow-hidden font-bold h-[40px] flex justify-between items-center`}\n            >\n              <div className=\"px-3 overflow-hidden text-ellipsis whitespace-nowrap\">\n                {tableData.name}\n              </div>\n              <div className=\"hidden group-hover:block\">\n                <div className=\"flex justify-end items-center mx-2 space-x-1.5\">\n                  <Button\n                    icon={tableData.locked ? <IconLock /> : <IconUnlock />}\n                    size=\"small\"\n                    theme=\"solid\"\n                    style={{\n                      backgroundColor: \"#2f68adb3\",\n                    }}\n                    disabled={layout.readOnly}\n                    onClick={lockUnlockTable}\n                  />\n                  <Button\n                    icon={<IconEdit />}\n                    size=\"small\"\n                    theme=\"solid\"\n                    style={{\n                      backgroundColor: \"#2f68adb3\",\n                    }}\n                    onClick={openEditor}\n                  />\n                  <Popover\n                    key={tableData.id}\n                    content={\n                      <div className=\"popover-theme\">\n                        <div className=\"mb-2\">\n                          <strong>{t(\"comment\")}:</strong>{\" \"}\n                          {tableData.comment === \"\" ? (\n                            t(\"not_set\")\n                          ) : (\n                            <div>{tableData.comment}</div>\n                          )}\n                        </div>\n                        <div>\n                          <strong\n                            className={`${\n                              tableData.indices.length === 0 ? \"\" : \"block\"\n                            }`}\n                          >\n                            {t(\"indices\")}:\n                          </strong>{\" \"}\n                          {tableData.indices.length === 0 ? (\n                            t(\"not_set\")\n                          ) : (\n                            <div>\n                              {tableData.indices.map((index, k) => (\n                                <div\n                                  key={k}\n                                  className={`flex items-center my-1 px-2 py-1 rounded ${\n                                    settings.mode === \"light\"\n                                      ? \"bg-gray-100\"\n                                      : \"bg-zinc-800\"\n                                  }`}\n                                >\n                                  <i className=\"fa-solid fa-thumbtack me-2 mt-1 text-slate-500\"></i>\n                                  <div>\n                                    {index.fields.map((f) => (\n                                      <Tag\n                                        color=\"blue\"\n                                        key={f}\n                                        className=\"me-1\"\n                                      >\n                                        {f}\n                                      </Tag>\n                                    ))}\n                                  </div>\n                                </div>\n                              ))}\n                            </div>\n                          )}\n                        </div>\n                        <Button\n                          icon={<IconDeleteStroked />}\n                          type=\"danger\"\n                          block\n                          style={{ marginTop: \"8px\" }}\n                          onClick={() => deleteTable(tableData.id)}\n                          disabled={layout.readOnly}\n                        >\n                          {t(\"delete\")}\n                        </Button>\n                      </div>\n                    }\n                    position=\"rightTop\"\n                    showArrow\n                    trigger=\"click\"\n                    style={{ width: \"200px\", wordBreak: \"break-word\" }}\n                  >\n                    <Button\n                      icon={<IconMore />}\n                      type=\"tertiary\"\n                      size=\"small\"\n                      style={{\n                        backgroundColor: \"#808080b3\",\n                        color: \"white\",\n                      }}\n                    />\n                  </Popover>\n                </div>\n              </div>\n            </div>\n            {tableData.comment && settings.showComments && (\n              <div className=\"text-xs px-3 line-clamp-5\">\n                {tableData.comment}\n              </div>\n            )}\n          </div>\n\n          {tableData.fields.map((e, i) => {\n            return settings.showFieldSummary ? (\n              <Popover\n                key={i}\n                content={\n                  <div className=\"popover-theme\">\n                    <div\n                      className=\"flex justify-between items-center pb-2\"\n                      style={{ direction: \"ltr\" }}\n                    >\n                      <p className=\"me-4 font-bold\">{e.name}</p>\n                      <p\n                        className={\n                          \"ms-4 font-mono \" + dbToTypes[database][e.type].color\n                        }\n                      >\n                        {e.type +\n                          ((dbToTypes[database][e.type].isSized ||\n                            dbToTypes[database][e.type].hasPrecision) &&\n                          e.size &&\n                          e.size !== \"\"\n                            ? \"(\" + e.size + \")\"\n                            : \"\")}\n                      </p>\n                    </div>\n                    <hr />\n                    {e.primary && (\n                      <Tag color=\"blue\" className=\"me-2 my-2\">\n                        {t(\"primary\")}\n                      </Tag>\n                    )}\n                    {e.unique && (\n                      <Tag color=\"amber\" className=\"me-2 my-2\">\n                        {t(\"unique\")}\n                      </Tag>\n                    )}\n                    {e.notNull && (\n                      <Tag color=\"purple\" className=\"me-2 my-2\">\n                        {t(\"not_null\")}\n                      </Tag>\n                    )}\n                    {e.increment && (\n                      <Tag color=\"green\" className=\"me-2 my-2\">\n                        {t(\"autoincrement\")}\n                      </Tag>\n                    )}\n                    <p>\n                      <strong>{t(\"default_value\")}: </strong>\n                      {e.default === \"\" ? t(\"not_set\") : e.default}\n                    </p>\n                    <p>\n                      <strong>{t(\"comment\")}: </strong>\n                      {e.comment === \"\" ? t(\"not_set\") : e.comment}\n                    </p>\n                  </div>\n                }\n                position=\"right\"\n                showArrow\n                style={\n                  isRtl(i18n.language)\n                    ? { direction: \"rtl\" }\n                    : { direction: \"ltr\" }\n                }\n              >\n                {field(e, i)}\n              </Popover>\n            ) : (\n              field(e, i)\n            );\n          })}\n        </div>\n      </foreignObject>\n      <SideSheet\n        title={t(\"edit\")}\n        size=\"small\"\n        visible={\n          selectedElement.element === ObjectType.TABLE &&\n          selectedElement.id === tableData.id &&\n          selectedElement.open &&\n          !layout.sidebar\n        }\n        onCancel={() =>\n          setSelectedElement((prev) => ({\n            ...prev,\n            open: !prev.open,\n          }))\n        }\n        style={{ paddingBottom: \"16px\" }}\n      >\n        <div className=\"sidesheet-theme\">\n          <TableInfo data={tableData} />\n        </div>\n      </SideSheet>\n    </>\n  );\n\n  function field(fieldData, index) {\n    return (\n      <div\n        className={`${\n          index === tableData.fields.length - 1\n            ? \"\"\n            : \"border-b border-gray-400\"\n        } group h-[36px] px-2 py-1 flex justify-between items-center gap-1 w-full overflow-hidden`}\n        onPointerEnter={(e) => {\n          if (!e.isPrimary) return;\n\n          setHoveredField(index);\n          setHoveredTable({\n            tableId: tableData.id,\n            fieldId: fieldData.id,\n          });\n        }}\n        onPointerLeave={(e) => {\n          if (!e.isPrimary) return;\n\n          setHoveredField(null);\n          setHoveredTable({\n            tableId: null,\n            fieldId: null,\n          });\n        }}\n        onPointerDown={(e) => {\n          // Required for onPointerLeave to trigger when a touch pointer leaves\n          // https://stackoverflow.com/a/70976017/1137077\n          e.target.releasePointerCapture(e.pointerId);\n        }}\n      >\n        <div\n          className={`${\n            hoveredField === index ? \"text-zinc-400\" : \"\"\n          } flex items-center gap-2 overflow-hidden`}\n        >\n          <button\n            className=\"shrink-0 w-[10px] h-[10px] bg-[#2f68adcc] rounded-full\"\n            onPointerDown={(e) => {\n              if (!e.isPrimary) return;\n\n              handleGripField();\n              setLinkingLine((prev) => ({\n                ...prev,\n                startFieldId: fieldData.id,\n                startTableId: tableData.id,\n                startX: tableData.x + 15,\n                startY:\n                  tableData.y +\n                  index * tableFieldHeight +\n                  tableHeaderHeight +\n                  tableColorStripHeight +\n                  getCommentHeight(\n                    tableData.comment,\n                    settings.tableWidth,\n                    settings.showComments,\n                  ) +\n                  14,\n                endX: tableData.x + 15,\n                endY:\n                  tableData.y +\n                  index * tableFieldHeight +\n                  tableHeaderHeight +\n                  tableColorStripHeight +\n                  getCommentHeight(\n                    tableData.comment,\n                    settings.tableWidth,\n                    settings.showComments,\n                  ) +\n                  14,\n              }));\n            }}\n          />\n          <span className=\"overflow-hidden text-ellipsis whitespace-nowrap\">\n            {fieldData.name}\n          </span>\n        </div>\n        <div className=\"text-zinc-400\">\n          {hoveredField === index ? (\n            <Button\n              theme=\"solid\"\n              size=\"small\"\n              style={{\n                backgroundColor: \"#d42020b3\",\n              }}\n              icon={<IconMinus />}\n              disabled={layout.readOnly}\n              onClick={() => {\n                if (layout.readOnly) return;\n                deleteField(fieldData, tableData.id);\n              }}\n            />\n          ) : settings.showDataTypes ? (\n            <div className=\"flex gap-1 items-center\">\n              {fieldData.primary && <IconKeyStroked />}\n              {!fieldData.notNull && <span className=\"font-mono\">?</span>}\n              <span\n                className={\n                  \"font-mono \" + dbToTypes[database][fieldData.type].color\n                }\n              >\n                {fieldData.type +\n                  ((dbToTypes[database][fieldData.type].isSized ||\n                    dbToTypes[database][fieldData.type].hasPrecision) &&\n                  fieldData.size &&\n                  fieldData.size !== \"\"\n                    ? `(${fieldData.size})`\n                    : \"\")}\n              </span>\n            </div>\n          ) : null}\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "src/components/EditorHeader/ControlPanel.jsx",
    "content": "import { useContext, useState } from \"react\";\nimport {\n  IconCaretdown,\n  IconChevronRight,\n  IconChevronLeft,\n  IconChevronUp,\n  IconChevronDown,\n  IconSaveStroked,\n  IconUndo,\n  IconRedo,\n  IconEdit,\n  IconShareStroked,\n} from \"@douyinfe/semi-icons\";\nimport { Link, useMatch, useNavigate, useParams } from \"react-router-dom\";\nimport icon from \"../../assets/icon_dark_64.png\";\nimport {\n  Button,\n  Divider,\n  Dropdown,\n  InputNumber,\n  Tooltip,\n  Spin,\n  Tag,\n  Toast,\n  Popconfirm,\n} from \"@douyinfe/semi-ui\";\nimport { toPng, toJpeg, toSvg } from \"html-to-image\";\nimport {\n  jsonToMySQL,\n  jsonToPostgreSQL,\n  jsonToSQLite,\n  jsonToMariaDB,\n  jsonToSQLServer,\n  jsonToOracleSQL,\n} from \"../../utils/exportSQL/generic\";\nimport {\n  ObjectType,\n  Action,\n  Tab,\n  State,\n  MODAL,\n  SIDESHEET,\n  DB,\n  IMPORT_FROM,\n  noteWidth,\n  pngExportPixelRatio,\n} from \"../../data/constants\";\nimport jsPDF from \"jspdf\";\nimport { useHotkeys } from \"react-hotkeys-hook\";\nimport { Validator } from \"jsonschema\";\nimport { areaSchema, noteSchema, tableSchema } from \"../../data/schemas\";\nimport { db } from \"../../data/db\";\nimport {\n  useLayout,\n  useSettings,\n  useTransform,\n  useDiagram,\n  useUndoRedo,\n  useSelect,\n  useSaveState,\n  useTypes,\n  useNotes,\n  useAreas,\n  useEnums,\n  useFullscreen,\n} from \"../../hooks\";\nimport { enterFullscreen, exitFullscreen } from \"../../utils/fullscreen\";\nimport { dataURItoBlob } from \"../../utils/utils\";\nimport { IconAddArea, IconAddNote, IconAddTable } from \"../../icons\";\nimport LayoutDropdown from \"./LayoutDropdown\";\nimport Sidesheet from \"./SideSheet/Sidesheet\";\nimport Modal from \"./Modal/Modal\";\nimport { useTranslation } from \"react-i18next\";\nimport { exportSQL } from \"../../utils/exportSQL\";\nimport { databases } from \"../../data/databases\";\nimport { jsonToMermaid } from \"../../utils/exportAs/mermaid\";\nimport { isRtl } from \"../../i18n/utils/rtl\";\nimport { jsonToDocumentation } from \"../../utils/exportAs/documentation\";\nimport { IdContext } from \"../Workspace\";\nimport { socials } from \"../../data/socials\";\nimport { toDBML } from \"../../utils/exportAs/dbml\";\nimport { exportSavedData } from \"../../utils/exportSavedData\";\nimport { nanoid } from \"nanoid\";\nimport { getTableHeight } from \"../../utils/utils\";\nimport { deleteFromCache, STORAGE_KEY } from \"../../utils/cache\";\nimport { useLiveQuery } from \"dexie-react-hooks\";\nimport { DateTime } from \"luxon\";\n\nexport default function ControlPanel({ title, setTitle, lastSaved }) {\n  const { id: diagramId } = useParams();\n\n  const [modal, setModal] = useState(MODAL.NONE);\n  const [sidesheet, setSidesheet] = useState(SIDESHEET.NONE);\n  const [showEditName, setShowEditName] = useState(false);\n  const [importDb, setImportDb] = useState(\"\");\n  const [exportData, setExportData] = useState({\n    data: null,\n    filename: `${title}_${new Date().toISOString()}`,\n    extension: \"\",\n  });\n  const [importFrom, setImportFrom] = useState(IMPORT_FROM.JSON);\n  const { saveState, setSaveState } = useSaveState();\n  const { layout, setLayout } = useLayout();\n  const { settings, setSettings } = useSettings();\n  const {\n    relationships,\n    tables,\n    setTables,\n    addTable,\n    updateTable,\n    deleteField,\n    deleteTable,\n    updateField,\n    setRelationships,\n    addRelationship,\n    deleteRelationship,\n    updateRelationship,\n    database,\n  } = useDiagram();\n  const { enums, setEnums, deleteEnum, addEnum, updateEnum } = useEnums();\n  const { types, addType, deleteType, updateType, setTypes } = useTypes();\n  const { notes, setNotes, updateNote, addNote, deleteNote } = useNotes();\n  const { areas, setAreas, updateArea, addArea, deleteArea } = useAreas();\n  const { undoStack, redoStack, setUndoStack, setRedoStack } = useUndoRedo();\n  const { selectedElement, setSelectedElement } = useSelect();\n  const { transform, setTransform } = useTransform();\n  const { t, i18n } = useTranslation();\n  const { version, gistId, setGistId } = useContext(IdContext);\n  const isTemplate = useMatch(\"/editor/templates/:id\");\n  const navigate = useNavigate();\n\n  const invertLayout = (component) =>\n    setLayout((prev) => ({ ...prev, [component]: !prev[component] }));\n\n  const undo = () => {\n    if (undoStack.length === 0) return;\n    const a = undoStack[undoStack.length - 1];\n    setUndoStack((prev) => prev.filter((_, i) => i !== prev.length - 1));\n\n    if (a.bulk) {\n      for (const element of a.elements) {\n        if (element.type === ObjectType.TABLE) {\n          updateTable(element.id, element.undo);\n        } else if (element.type === ObjectType.AREA) {\n          updateArea(element.id, element.undo);\n        } else if (element.type === ObjectType.NOTE) {\n          updateNote(element.id, element.undo);\n        }\n      }\n      setRedoStack((prev) => [...prev, a]);\n      return;\n    }\n\n    if (a.action === Action.ADD) {\n      if (a.element === ObjectType.TABLE) {\n        deleteTable(a.data.table.id, false);\n      } else if (a.element === ObjectType.AREA) {\n        deleteArea(areas[areas.length - 1].id, false);\n      } else if (a.element === ObjectType.NOTE) {\n        deleteNote(notes[notes.length - 1].id, false);\n      } else if (a.element === ObjectType.RELATIONSHIP) {\n        deleteRelationship(a.data.relationship.id, false);\n      } else if (a.element === ObjectType.TYPE) {\n        deleteType(a.data.type.id, false);\n      } else if (a.element === ObjectType.ENUM) {\n        deleteEnum(a.data.enum.id, false);\n      }\n      setRedoStack((prev) => [...prev, a]);\n    } else if (a.action === Action.MOVE) {\n      if (a.element === ObjectType.TABLE) {\n        const { x, y } = tables.find((t) => t.id === a.id);\n        setRedoStack((prev) => [...prev, { ...a, x, y }]);\n        updateTable(a.id, { x: a.x, y: a.y });\n      } else if (a.element === ObjectType.AREA) {\n        setRedoStack((prev) => [\n          ...prev,\n          { ...a, x: areas[a.id].x, y: areas[a.id].y },\n        ]);\n        updateArea(a.id, { x: a.x, y: a.y });\n      } else if (a.element === ObjectType.NOTE) {\n        setRedoStack((prev) => [\n          ...prev,\n          { ...a, x: notes[a.id].x, y: notes[a.id].y },\n        ]);\n        updateNote(a.id, { x: a.x, y: a.y });\n      }\n    } else if (a.action === Action.DELETE) {\n      if (a.element === ObjectType.TABLE) {\n        a.data.relationship.forEach((x) => addRelationship(x, false));\n        addTable(a.data, false);\n      } else if (a.element === ObjectType.RELATIONSHIP) {\n        addRelationship(a.data, false);\n      } else if (a.element === ObjectType.NOTE) {\n        addNote(a.data, false);\n      } else if (a.element === ObjectType.AREA) {\n        addArea(a.data, false);\n      } else if (a.element === ObjectType.TYPE) {\n        addType(a.data, false);\n      } else if (a.element === ObjectType.ENUM) {\n        addEnum(a.data, false);\n      }\n      setRedoStack((prev) => [...prev, a]);\n    } else if (a.action === Action.EDIT) {\n      if (a.element === ObjectType.AREA) {\n        updateArea(a.aid, a.undo);\n      } else if (a.element === ObjectType.NOTE) {\n        updateNote(a.nid, a.undo);\n      } else if (a.element === ObjectType.TABLE) {\n        const table = tables.find((t) => t.id === a.tid);\n        if (a.component === \"field\") {\n          updateField(a.tid, a.fid, a.undo);\n        } else if (a.component === \"field_delete\") {\n          setRelationships((prev) => {\n            let temp = [...prev];\n            a.data.relationship.forEach((r) => {\n              temp.splice(r.id, 0, r);\n            });\n            return temp;\n          });\n          const updatedFields = table.fields.slice();\n          updatedFields.splice(a.data.index, 0, a.data.field);\n          updateTable(a.tid, { fields: updatedFields });\n        } else if (a.component === \"field_add\") {\n          updateTable(a.tid, {\n            fields: table.fields.filter((e) => e.id !== a.fid),\n          });\n        } else if (a.component === \"index_add\") {\n          updateTable(a.tid, {\n            indices: table.indices\n              .filter((e) => e.id !== table.indices.length - 1)\n              .map((t, i) => ({ ...t, id: i })),\n          });\n        } else if (a.component === \"index\") {\n          updateTable(a.tid, {\n            indices: table.indices.map((index) =>\n              index.id === a.iid\n                ? {\n                    ...index,\n                    ...a.undo,\n                  }\n                : index,\n            ),\n          });\n        } else if (a.component === \"index_delete\") {\n          const updatedIndices = table.indices.slice();\n          updatedIndices.splice(a.data.id, 0, a.data);\n          updateTable(a.tid, {\n            indices: updatedIndices.map((t, i) => ({ ...t, id: i })),\n          });\n        } else if (a.component === \"self\") {\n          updateTable(a.tid, a.undo);\n        }\n      } else if (a.element === ObjectType.RELATIONSHIP) {\n        updateRelationship(a.rid, a.undo);\n      } else if (a.element === ObjectType.TYPE) {\n        if (a.component === \"field_add\") {\n          const type = types.find((t, i) =>\n            typeof a.tid === \"number\" ? i === a.tid : t.id === a.tid,\n          );\n          updateType(a.tid, {\n            fields: type.fields.filter((f, i) =>\n              f.id ? f.id !== a.data.field.id : i !== type.fields.length - 1,\n            ),\n          });\n        }\n        if (a.component === \"field\") {\n          updateType(a.tid, {\n            fields: types[a.tid].fields.map((e, i) =>\n              i === a.fid ? { ...e, ...a.undo } : e,\n            ),\n          });\n        } else if (a.component === \"field_delete\") {\n          setTypes((prev) =>\n            prev.map((t, i) => {\n              if (i === a.tid) {\n                const temp = t.fields.slice();\n                temp.splice(a.fid, 0, a.data);\n                return { ...t, fields: temp };\n              }\n              return t;\n            }),\n          );\n        } else if (a.component === \"self\") {\n          updateType(a.tid, a.undo);\n          if (a.updatedFields) {\n            if (a.undo.name) {\n              a.updatedFields.forEach((x) =>\n                updateField(x.tid, x.fid, { type: a.undo.name.toUpperCase() }),\n              );\n            }\n          }\n        }\n      } else if (a.element === ObjectType.ENUM) {\n        updateEnum(a.id, a.undo);\n        if (a.updatedFields) {\n          if (a.undo.name) {\n            a.updatedFields.forEach((x) =>\n              updateField(x.tid, x.fid, { type: a.undo.name.toUpperCase() }),\n            );\n          }\n        }\n      }\n      setRedoStack((prev) => [...prev, a]);\n    }\n  };\n\n  const redo = () => {\n    if (redoStack.length === 0) return;\n    const a = redoStack[redoStack.length - 1];\n    setRedoStack((prev) => prev.filter((e, i) => i !== prev.length - 1));\n\n    if (a.bulk) {\n      for (const element of a.elements) {\n        if (element.type === ObjectType.TABLE) {\n          updateTable(element.id, element.redo);\n        } else if (element.type === ObjectType.AREA) {\n          updateArea(element.id, element.redo);\n        } else if (element.type === ObjectType.NOTE) {\n          updateNote(element.id, element.redo);\n        }\n      }\n      setUndoStack((prev) => [...prev, a]);\n      return;\n    }\n\n    if (a.action === Action.ADD) {\n      if (a.element === ObjectType.TABLE) {\n        addTable(a.data, false);\n      } else if (a.element === ObjectType.AREA) {\n        addArea(null, false);\n      } else if (a.element === ObjectType.NOTE) {\n        addNote(null, false);\n      } else if (a.element === ObjectType.RELATIONSHIP) {\n        addRelationship(a.data, false);\n      } else if (a.element === ObjectType.TYPE) {\n        addType(a.data, false);\n      } else if (a.element === ObjectType.ENUM) {\n        addEnum(a.data, false);\n      }\n      setUndoStack((prev) => [...prev, a]);\n    } else if (a.action === Action.MOVE) {\n      if (a.element === ObjectType.TABLE) {\n        const { x, y } = tables.find((t) => t.id == a.id);\n        setUndoStack((prev) => [...prev, { ...a, x, y }]);\n        updateTable(a.id, { x: a.x, y: a.y });\n      } else if (a.element === ObjectType.AREA) {\n        setUndoStack((prev) => [\n          ...prev,\n          { ...a, x: areas[a.id].x, y: areas[a.id].y },\n        ]);\n        updateArea(a.id, { x: a.x, y: a.y });\n      } else if (a.element === ObjectType.NOTE) {\n        setUndoStack((prev) => [\n          ...prev,\n          { ...a, x: notes[a.id].x, y: notes[a.id].y },\n        ]);\n        updateNote(a.id, { x: a.x, y: a.y });\n      }\n    } else if (a.action === Action.DELETE) {\n      if (a.element === ObjectType.TABLE) {\n        deleteTable(a.data.table.id, false);\n      } else if (a.element === ObjectType.RELATIONSHIP) {\n        deleteRelationship(a.data.relationship.id, false);\n      } else if (a.element === ObjectType.NOTE) {\n        deleteNote(a.data.id, false);\n      } else if (a.element === ObjectType.AREA) {\n        deleteArea(a.data.id, false);\n      } else if (a.element === ObjectType.TYPE) {\n        deleteType(a.data.type.id, false);\n      } else if (a.element === ObjectType.ENUM) {\n        deleteEnum(a.data.enum.id, false);\n      }\n      setUndoStack((prev) => [...prev, a]);\n    } else if (a.action === Action.EDIT) {\n      if (a.element === ObjectType.AREA) {\n        updateArea(a.aid, a.redo);\n      } else if (a.element === ObjectType.NOTE) {\n        updateNote(a.nid, a.redo);\n      } else if (a.element === ObjectType.TABLE) {\n        const table = tables.find((t) => t.id === a.tid);\n        if (a.component === \"field\") {\n          updateField(a.tid, a.fid, a.redo);\n        } else if (a.component === \"field_delete\") {\n          deleteField(a.data.field, a.tid, false);\n        } else if (a.component === \"field_add\") {\n          updateTable(a.tid, {\n            fields: [\n              ...table.fields,\n              {\n                name: \"\",\n                type: \"\",\n                default: \"\",\n                check: \"\",\n                primary: false,\n                unique: false,\n                notNull: false,\n                increment: false,\n                comment: \"\",\n                id: nanoid(),\n              },\n            ],\n          });\n        } else if (a.component === \"index_add\") {\n          updateTable(a.tid, {\n            indices: [\n              ...table.indices,\n              {\n                id: table.indices.length,\n                name: `index_${table.indices.length}`,\n                fields: [],\n              },\n            ],\n          });\n        } else if (a.component === \"index\") {\n          updateTable(a.tid, {\n            indices: table.indices.map((index) =>\n              index.id === a.iid\n                ? {\n                    ...index,\n                    ...a.redo,\n                  }\n                : index,\n            ),\n          });\n        } else if (a.component === \"index_delete\") {\n          updateTable(a.tid, {\n            indices: table.indices\n              .filter((e) => e.id !== a.data.id)\n              .map((t, i) => ({ ...t, id: i })),\n          });\n        } else if (a.component === \"self\") {\n          updateTable(a.tid, a.redo, false);\n        }\n      } else if (a.element === ObjectType.RELATIONSHIP) {\n        updateRelationship(a.rid, a.redo);\n      } else if (a.element === ObjectType.TYPE) {\n        if (a.component === \"field_add\") {\n          const type = types.find((t, i) =>\n            typeof a.tid === \"number\" ? i === a.tid : t.id === a.tid,\n          );\n          updateType(a.tid, {\n            fields: [...type.fields, a.data.field],\n          });\n        } else if (a.component === \"field\") {\n          updateType(a.tid, {\n            fields: types[a.tid].fields.map((e, i) =>\n              i === a.fid ? { ...e, ...a.redo } : e,\n            ),\n          });\n        } else if (a.component === \"field_delete\") {\n          updateType(a.tid, {\n            fields: types[a.tid].fields.filter((field, i) => i !== a.fid),\n          });\n        } else if (a.component === \"self\") {\n          updateType(a.tid, a.redo);\n          if (a.updatedFields) {\n            if (a.redo.name) {\n              a.updatedFields.forEach((x) =>\n                updateField(x.tid, x.fid, { type: a.redo.name.toUpperCase() }),\n              );\n            }\n          }\n        }\n      } else if (a.element === ObjectType.ENUM) {\n        updateEnum(a.id, a.redo);\n        if (a.updatedFields) {\n          if (a.redo.name) {\n            a.updatedFields.forEach((x) =>\n              updateField(x.tid, x.fid, { type: a.redo.name.toUpperCase() }),\n            );\n          }\n        }\n      }\n      setUndoStack((prev) => [...prev, a]);\n    }\n  };\n\n  const fileImport = () => setModal(MODAL.IMPORT);\n  const viewGrid = () =>\n    setSettings((prev) => ({ ...prev, showGrid: !prev.showGrid }));\n  const snapToGrid = () =>\n    setSettings((prev) => ({ ...prev, snapToGrid: !prev.snapToGrid }));\n  const zoomIn = () =>\n    setTransform((prev) => ({ ...prev, zoom: prev.zoom * 1.2 }));\n  const zoomOut = () =>\n    setTransform((prev) => ({ ...prev, zoom: prev.zoom / 1.2 }));\n  const viewStrictMode = () => {\n    setSettings((prev) => ({ ...prev, strictMode: !prev.strictMode }));\n  };\n  const viewFieldSummary = () => {\n    setSettings((prev) => ({\n      ...prev,\n      showFieldSummary: !prev.showFieldSummary,\n    }));\n  };\n  const copyAsImage = () => {\n    toPng(document.getElementById(\"canvas\"), {\n      pixelRatio: pngExportPixelRatio,\n    }).then(function (dataUrl) {\n      const blob = dataURItoBlob(dataUrl);\n      navigator.clipboard\n        .write([new ClipboardItem({ \"image/png\": blob })])\n        .then(() => {\n          Toast.success(t(\"copied_to_clipboard\"));\n        })\n        .catch(() => {\n          Toast.error(t(\"oops_smth_went_wrong\"));\n        });\n    });\n  };\n  const resetView = () =>\n    setTransform((prev) => ({ ...prev, zoom: 1, pan: { x: 0, y: 0 } }));\n  const fitWindow = () => {\n    const canvas = document.getElementById(\"canvas\").getBoundingClientRect();\n\n    const minMaxXY = {\n      minX: Infinity,\n      minY: Infinity,\n      maxX: -Infinity,\n      maxY: -Infinity,\n    };\n\n    tables.forEach((table) => {\n      minMaxXY.minX = Math.min(minMaxXY.minX, table.x);\n      minMaxXY.minY = Math.min(minMaxXY.minY, table.y);\n      minMaxXY.maxX = Math.max(minMaxXY.maxX, table.x + settings.tableWidth);\n      minMaxXY.maxY = Math.max(\n        minMaxXY.maxY,\n        table.y +\n          getTableHeight(table, settings.tableWidth, settings.showComments),\n      );\n    });\n\n    areas.forEach((area) => {\n      minMaxXY.minX = Math.min(minMaxXY.minX, area.x);\n      minMaxXY.minY = Math.min(minMaxXY.minY, area.y);\n      minMaxXY.maxX = Math.max(minMaxXY.maxX, area.x + area.width);\n      minMaxXY.maxY = Math.max(minMaxXY.maxY, area.y + area.height);\n    });\n\n    notes.forEach((note) => {\n      minMaxXY.minX = Math.min(minMaxXY.minX, note.x);\n      minMaxXY.minY = Math.min(minMaxXY.minY, note.y);\n      minMaxXY.maxX = Math.max(\n        minMaxXY.maxX,\n        note.x + (note.width ?? noteWidth),\n      );\n      minMaxXY.maxY = Math.max(minMaxXY.maxY, note.y + note.height);\n    });\n\n    const padding = 10;\n    const width = minMaxXY.maxX - minMaxXY.minX + padding;\n    const height = minMaxXY.maxY - minMaxXY.minY + padding;\n\n    const scaleX = canvas.width / width;\n    const scaleY = canvas.height / height;\n    // Making sure the scale is a multiple of 0.05\n    const scale = Math.floor(Math.min(scaleX, scaleY) * 20) / 20;\n\n    const centerX = (minMaxXY.minX + minMaxXY.maxX) / 2;\n    const centerY = (minMaxXY.minY + minMaxXY.maxY) / 2;\n\n    setTransform((prev) => ({\n      ...prev,\n      zoom: scale,\n      pan: { x: centerX, y: centerY },\n    }));\n  };\n  const edit = () => {\n    if (selectedElement.element === ObjectType.TABLE) {\n      if (!layout.sidebar) {\n        setSelectedElement((prev) => ({\n          ...prev,\n          open: true,\n        }));\n      } else {\n        setSelectedElement((prev) => ({\n          ...prev,\n          open: true,\n          currentTab: Tab.TABLES,\n        }));\n        if (selectedElement.currentTab !== Tab.TABLES) return;\n        document\n          .getElementById(`scroll_table_${selectedElement.id}`)\n          .scrollIntoView({ behavior: \"smooth\" });\n      }\n    } else if (selectedElement.element === ObjectType.AREA) {\n      if (layout.sidebar) {\n        setSelectedElement((prev) => ({\n          ...prev,\n          currentTab: Tab.AREAS,\n        }));\n        if (selectedElement.currentTab !== Tab.AREAS) return;\n        document\n          .getElementById(`scroll_area_${selectedElement.id}`)\n          .scrollIntoView({ behavior: \"smooth\" });\n      } else {\n        setSelectedElement((prev) => ({\n          ...prev,\n          open: true,\n          editFromToolbar: true,\n        }));\n      }\n    } else if (selectedElement.element === ObjectType.NOTE) {\n      if (layout.sidebar) {\n        setSelectedElement((prev) => ({\n          ...prev,\n          currentTab: Tab.NOTES,\n          open: false,\n        }));\n        if (selectedElement.currentTab !== Tab.NOTES) return;\n        document\n          .getElementById(`scroll_note_${selectedElement.id}`)\n          .scrollIntoView({ behavior: \"smooth\" });\n      } else {\n        setSelectedElement((prev) => ({\n          ...prev,\n          open: true,\n          editFromToolbar: true,\n        }));\n      }\n    }\n  };\n  const del = () => {\n    if (layout.readOnly) {\n      return;\n    }\n    switch (selectedElement.element) {\n      case ObjectType.TABLE:\n        deleteTable(selectedElement.id);\n        break;\n      case ObjectType.NOTE:\n        deleteNote(selectedElement.id);\n        break;\n      case ObjectType.AREA:\n        deleteArea(selectedElement.id);\n        break;\n      default:\n        break;\n    }\n  };\n  const duplicate = () => {\n    if (layout.readOnly) {\n      return;\n    }\n    switch (selectedElement.element) {\n      case ObjectType.TABLE: {\n        const copiedTable = tables.find((t) => t.id === selectedElement.id);\n        addTable({\n          table: {\n            ...copiedTable,\n            x: copiedTable.x + 20,\n            y: copiedTable.y + 20,\n            id: nanoid(),\n          },\n        });\n        break;\n      }\n      case ObjectType.NOTE:\n        addNote({\n          ...notes[selectedElement.id],\n          x: notes[selectedElement.id].x + 20,\n          y: notes[selectedElement.id].y + 20,\n          id: notes.length,\n        });\n        break;\n      case ObjectType.AREA:\n        addArea({\n          ...areas[selectedElement.id],\n          x: areas[selectedElement.id].x + 20,\n          y: areas[selectedElement.id].y + 20,\n          id: areas.length,\n        });\n        break;\n      default:\n        break;\n    }\n  };\n  const copy = () => {\n    switch (selectedElement.element) {\n      case ObjectType.TABLE:\n        navigator.clipboard\n          .writeText(\n            JSON.stringify(tables.find((t) => t.id === selectedElement.id)),\n          )\n          .catch(() => Toast.error(t(\"oops_smth_went_wrong\")));\n        break;\n      case ObjectType.NOTE:\n        navigator.clipboard\n          .writeText(JSON.stringify({ ...notes[selectedElement.id] }))\n          .catch(() => Toast.error(t(\"oops_smth_went_wrong\")));\n        break;\n      case ObjectType.AREA:\n        navigator.clipboard\n          .writeText(JSON.stringify({ ...areas[selectedElement.id] }))\n          .catch(() => Toast.error(t(\"oops_smth_went_wrong\")));\n        break;\n      default:\n        break;\n    }\n  };\n  const paste = () => {\n    if (layout.readOnly) {\n      return;\n    }\n    navigator.clipboard.readText().then((text) => {\n      let obj = null;\n      try {\n        obj = JSON.parse(text);\n      } catch (error) {\n        return;\n      }\n      const v = new Validator();\n      if (v.validate(obj, tableSchema).valid) {\n        addTable({\n          table: {\n            ...obj,\n            x: obj.x + 20,\n            y: obj.y + 20,\n            id: nanoid(),\n          },\n        });\n      } else if (v.validate(obj, areaSchema).valid) {\n        addArea({\n          ...obj,\n          x: obj.x + 20,\n          y: obj.y + 20,\n          id: areas.length,\n        });\n      } else if (v.validate(obj, noteSchema)) {\n        addNote({\n          ...obj,\n          x: obj.x + 20,\n          y: obj.y + 20,\n          id: notes.length,\n        });\n      }\n    });\n  };\n  const cut = () => {\n    if (layout.readOnly) {\n      return;\n    }\n    copy();\n    del();\n  };\n  const toggleDBMLEditor = () => {\n    setLayout((prev) => ({ ...prev, dbmlEditor: !prev.dbmlEditor }));\n  };\n  const save = () => setSaveState(State.SAVING);\n  const recentlyOpenedDiagrams = useLiveQuery(() =>\n    db.diagrams.orderBy(\"lastModified\").reverse().limit(10).toArray(),\n  );\n\n  const open = () => setModal(MODAL.OPEN);\n  const saveDiagramAs = () => setModal(MODAL.SAVEAS);\n  const fullscreen = useFullscreen();\n\n  const menu = {\n    file: {\n      new: {\n        function: () => setModal(MODAL.NEW),\n      },\n      new_window: {\n        function: () => window.open(\"/editor\", \"_blank\"),\n      },\n      open: {\n        function: open,\n        shortcut: \"Ctrl+O\",\n      },\n      open_recent: {\n        children: [\n          ...(recentlyOpenedDiagrams && recentlyOpenedDiagrams.length > 0\n            ? [\n                ...recentlyOpenedDiagrams.map((diagram) => ({\n                  name: diagram.name,\n                  label: DateTime.fromJSDate(new Date(diagram.lastModified))\n                    .setLocale(i18n.language)\n                    .toRelative(),\n                  function: () => {\n                    navigate(`/editor/diagrams/${diagram.diagramId}`);\n                  },\n                })),\n                { divider: true },\n                {\n                  name: t(\"see_all\"),\n                  function: () => open(),\n                },\n              ]\n            : [\n                {\n                  name: t(\"no_saved_diagrams\"),\n                  disabled: true,\n                },\n              ]),\n        ],\n\n        function: () => {},\n      },\n      save: {\n        function: save,\n        shortcut: \"Ctrl+S\",\n        disabled: layout.readOnly,\n      },\n      save_as: {\n        function: saveDiagramAs,\n        shortcut: \"Ctrl+Shift+S\",\n        disabled: layout.readOnly,\n      },\n      save_as_template: {\n        function: async () => {\n          await db.templates\n            .add({\n              title: title,\n              tables: tables,\n              database: database,\n              relationships: relationships,\n              notes: notes,\n              subjectAreas: areas,\n              custom: 1,\n              templateId: crypto.randomUUID(),\n              ...(databases[database].hasEnums && { enums: enums }),\n              ...(databases[database].hasTypes && { types: types }),\n            })\n            .then(() => {\n              Toast.success(t(\"template_saved\"));\n            });\n        },\n      },\n      rename: {\n        function: () => {\n          setModal(MODAL.RENAME);\n        },\n        disabled: layout.readOnly,\n      },\n      delete_diagram: {\n        warning: {\n          title: t(\"delete_diagram\"),\n          message: t(\"are_you_sure_delete_diagram\"),\n        },\n        function: async () => {\n          await db.diagrams\n            .where(\"diagramId\")\n            .equals(diagramId)\n            .delete()\n            .then(() => {\n              setTitle(\"Untitled diagram\");\n              setTables([]);\n              setRelationships([]);\n              setAreas([]);\n              setNotes([]);\n              setTypes([]);\n              setEnums([]);\n              setUndoStack([]);\n              setRedoStack([]);\n              setGistId(\"\");\n              navigate(\"/editor/templates/blank\", { replace: true });\n            })\n            .catch(() => Toast.error(t(\"oops_smth_went_wrong\")));\n        },\n      },\n      import_from: {\n        children: [\n          {\n            function: () => {\n              setModal(MODAL.IMPORT);\n              setImportFrom(IMPORT_FROM.JSON);\n            },\n            name: \"JSON\",\n            disabled: layout.readOnly,\n          },\n          {\n            function: () => {\n              setModal(MODAL.IMPORT);\n              setImportFrom(IMPORT_FROM.DBML);\n            },\n            name: \"DBML\",\n            disabled: layout.readOnly,\n          },\n        ],\n      },\n      import_from_source: {\n        ...(database === DB.GENERIC && {\n          children: [\n            {\n              function: () => {\n                setModal(MODAL.IMPORT_SRC);\n                setImportDb(DB.MYSQL);\n              },\n              name: \"MySQL\",\n              disabled: layout.readOnly,\n            },\n            {\n              function: () => {\n                setModal(MODAL.IMPORT_SRC);\n                setImportDb(DB.POSTGRES);\n              },\n              name: \"PostgreSQL\",\n              disabled: layout.readOnly,\n            },\n            {\n              function: () => {\n                setModal(MODAL.IMPORT_SRC);\n                setImportDb(DB.SQLITE);\n              },\n              name: \"SQLite\",\n              disabled: layout.readOnly,\n            },\n            {\n              function: () => {\n                setModal(MODAL.IMPORT_SRC);\n                setImportDb(DB.MARIADB);\n              },\n              name: \"MariaDB\",\n              disabled: layout.readOnly,\n            },\n            {\n              function: () => {\n                setModal(MODAL.IMPORT_SRC);\n                setImportDb(DB.MSSQL);\n              },\n              name: \"MSSQL\",\n              disabled: layout.readOnly,\n            },\n            {\n              function: () => {\n                setModal(MODAL.IMPORT_SRC);\n                setImportDb(DB.ORACLESQL);\n              },\n              name: \"Oracle\",\n              label: \"Beta\",\n              disabled: layout.readOnly,\n            },\n          ],\n        }),\n        function: () => {\n          if (database === DB.GENERIC) return;\n\n          setModal(MODAL.IMPORT_SRC);\n        },\n        disabled: layout.readOnly,\n      },\n      export_source: {\n        ...(database === DB.GENERIC && {\n          children: [\n            {\n              name: \"MySQL\",\n              function: () => {\n                setModal(MODAL.CODE);\n                const src = jsonToMySQL({\n                  tables: tables,\n                  references: relationships,\n                  types: types,\n                  database: database,\n                });\n                setExportData((prev) => ({\n                  ...prev,\n                  data: src,\n                  extension: \"sql\",\n                }));\n              },\n            },\n            {\n              name: \"PostgreSQL\",\n              function: () => {\n                setModal(MODAL.CODE);\n                const src = jsonToPostgreSQL({\n                  tables: tables,\n                  references: relationships,\n                  types: types,\n                  database: database,\n                });\n                setExportData((prev) => ({\n                  ...prev,\n                  data: src,\n                  extension: \"sql\",\n                }));\n              },\n            },\n            {\n              name: \"SQLite\",\n              function: () => {\n                setModal(MODAL.CODE);\n                const src = jsonToSQLite({\n                  tables: tables,\n                  references: relationships,\n                  types: types,\n                  database: database,\n                });\n                setExportData((prev) => ({\n                  ...prev,\n                  data: src,\n                  extension: \"sql\",\n                }));\n              },\n            },\n            {\n              name: \"MariaDB\",\n              function: () => {\n                setModal(MODAL.CODE);\n                const src = jsonToMariaDB({\n                  tables: tables,\n                  references: relationships,\n                  types: types,\n                  database: database,\n                });\n                setExportData((prev) => ({\n                  ...prev,\n                  data: src,\n                  extension: \"sql\",\n                }));\n              },\n            },\n            {\n              name: \"MSSQL\",\n              function: () => {\n                setModal(MODAL.CODE);\n                const src = jsonToSQLServer({\n                  tables: tables,\n                  references: relationships,\n                  types: types,\n                  database: database,\n                });\n                setExportData((prev) => ({\n                  ...prev,\n                  data: src,\n                  extension: \"sql\",\n                }));\n              },\n            },\n            {\n              label: \"Beta\",\n              name: \"Oracle\",\n              function: () => {\n                setModal(MODAL.CODE);\n                const src = jsonToOracleSQL({\n                  tables: tables,\n                  references: relationships,\n                  types: types,\n                  database: database,\n                });\n                setExportData((prev) => ({\n                  ...prev,\n                  data: src,\n                  extension: \"sql\",\n                }));\n              },\n            },\n          ],\n        }),\n        function: () => {\n          if (database === DB.GENERIC) return;\n          setModal(MODAL.CODE);\n          const src = exportSQL({\n            tables: tables,\n            references: relationships,\n            types: types,\n            database: database,\n            enums: enums,\n          });\n          setExportData((prev) => ({\n            ...prev,\n            data: src,\n            extension: \"sql\",\n          }));\n        },\n      },\n      export_as: {\n        children: [\n          {\n            name: \"PNG\",\n            function: () => {\n              toPng(document.getElementById(\"canvas\"), {\n                pixelRatio: pngExportPixelRatio,\n              }).then(function (dataUrl) {\n                setExportData((prev) => ({\n                  ...prev,\n                  data: dataUrl,\n                  extension: \"png\",\n                }));\n              });\n              setModal(MODAL.IMG);\n            },\n          },\n          {\n            name: \"JPEG\",\n            function: () => {\n              toJpeg(document.getElementById(\"canvas\"), { quality: 0.95 }).then(\n                function (dataUrl) {\n                  setExportData((prev) => ({\n                    ...prev,\n                    data: dataUrl,\n                    extension: \"jpeg\",\n                  }));\n                },\n              );\n              setModal(MODAL.IMG);\n            },\n          },\n          {\n            name: \"SVG\",\n            function: () => {\n              const filter = (node) => node.tagName !== \"i\";\n              toSvg(document.getElementById(\"canvas\"), { filter: filter }).then(\n                function (dataUrl) {\n                  setExportData((prev) => ({\n                    ...prev,\n                    data: dataUrl,\n                    extension: \"svg\",\n                  }));\n                },\n              );\n              setModal(MODAL.IMG);\n            },\n          },\n          {\n            name: \"JSON\",\n            function: () => {\n              setModal(MODAL.CODE);\n              const result = JSON.stringify(\n                {\n                  tables: tables,\n                  relationships: relationships,\n                  notes: notes,\n                  subjectAreas: areas,\n                  database: database,\n                  ...(databases[database].hasTypes && { types: types }),\n                  ...(databases[database].hasEnums && { enums: enums }),\n                  title: title,\n                },\n                null,\n                2,\n              );\n              setExportData((prev) => ({\n                ...prev,\n                data: result,\n                extension: \"json\",\n              }));\n            },\n          },\n          {\n            name: \"DBML\",\n            function: () => {\n              setModal(MODAL.CODE);\n              const result = toDBML({\n                tables,\n                relationships,\n                enums,\n                database,\n              });\n              setExportData((prev) => ({\n                ...prev,\n                data: result,\n                extension: \"dbml\",\n              }));\n            },\n          },\n          {\n            name: \"PDF\",\n            function: () => {\n              const canvas = document.getElementById(\"canvas\");\n              toJpeg(canvas).then(function (dataUrl) {\n                const doc = new jsPDF(\"l\", \"px\", [\n                  canvas.offsetWidth,\n                  canvas.offsetHeight,\n                ]);\n                doc.addImage(\n                  dataUrl,\n                  \"jpeg\",\n                  0,\n                  0,\n                  canvas.offsetWidth,\n                  canvas.offsetHeight,\n                );\n                doc.save(`${exportData.filename}.pdf`);\n              });\n            },\n          },\n          {\n            name: \"Mermaid\",\n            function: () => {\n              setModal(MODAL.CODE);\n              const result = jsonToMermaid({\n                tables: tables,\n                relationships: relationships,\n                notes: notes,\n                subjectAreas: areas,\n                database: database,\n                title: title,\n              });\n              setExportData((prev) => ({\n                ...prev,\n                data: result,\n                extension: \"md\",\n              }));\n            },\n          },\n          {\n            name: \"Markdown\",\n            function: () => {\n              setModal(MODAL.CODE);\n              const result = jsonToDocumentation({\n                tables: tables,\n                relationships: relationships,\n                notes: notes,\n                subjectAreas: areas,\n                database: database,\n                title: title,\n                ...(databases[database].hasTypes && { types: types }),\n                ...(databases[database].hasEnums && { enums: enums }),\n              });\n              setExportData((prev) => ({\n                ...prev,\n                data: result,\n                extension: \"md\",\n              }));\n            },\n          },\n        ],\n        function: () => {},\n      },\n      exit: {\n        function: () => {\n          save();\n          if (saveState === State.SAVED) navigate(\"/\");\n        },\n      },\n    },\n    edit: {\n      undo: {\n        function: undo,\n        shortcut: \"Ctrl+Z\",\n        disabled: layout.readOnly || undoStack.length === 0,\n      },\n      redo: {\n        function: redo,\n        shortcut: \"Ctrl+Y\",\n        disabled: layout.readOnly || redoStack.length === 0,\n      },\n      clear: {\n        warning: {\n          title: t(\"clear\"),\n          message: t(\"are_you_sure_clear\"),\n        },\n        function: async () => {\n          setTables([]);\n          setRelationships([]);\n          setAreas([]);\n          setNotes([]);\n          setEnums([]);\n          setTypes([]);\n          setUndoStack([]);\n          setRedoStack([]);\n        },\n        disabled: layout.readOnly,\n      },\n      edit: {\n        function: edit,\n        shortcut: \"Ctrl+E\",\n        disabled: layout.readOnly,\n      },\n      cut: {\n        function: cut,\n        shortcut: \"Ctrl+X\",\n        disabled: layout.readOnly,\n      },\n      copy: {\n        function: copy,\n        shortcut: \"Ctrl+C\",\n      },\n      paste: {\n        function: paste,\n        shortcut: \"Ctrl+V\",\n        disabled: layout.readOnly,\n      },\n      duplicate: {\n        function: duplicate,\n        shortcut: \"Ctrl+D\",\n        disabled: layout.readOnly,\n      },\n      delete: {\n        function: del,\n        shortcut: \"Del\",\n        disabled: layout.readOnly,\n      },\n      copy_as_image: {\n        function: copyAsImage,\n        shortcut: \"Ctrl+Alt+C\",\n      },\n    },\n    view: {\n      header: {\n        state: layout.header ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: () =>\n          setLayout((prev) => ({ ...prev, header: !prev.header })),\n      },\n      sidebar: {\n        state: layout.sidebar ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: () =>\n          setLayout((prev) => ({ ...prev, sidebar: !prev.sidebar })),\n      },\n      issues: {\n        state: layout.issues ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: () =>\n          setLayout((prev) => ({ ...prev, issues: !prev.issues })),\n      },\n      dbml_view: {\n        state: layout.dbmlEditor ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: toggleDBMLEditor,\n        shortcut: \"Alt+E\",\n      },\n      strict_mode: {\n        state: settings.strictMode ? (\n          <i className=\"bi bi-toggle-off\" />\n        ) : (\n          <i className=\"bi bi-toggle-on\" />\n        ),\n        function: viewStrictMode,\n        shortcut: \"Ctrl+Shift+M\",\n      },\n      presentation_mode: {\n        function: () => {\n          setLayout((prev) => ({\n            ...prev,\n            header: false,\n            sidebar: false,\n            toolbar: false,\n          }));\n          enterFullscreen();\n        },\n      },\n      field_details: {\n        state: settings.showFieldSummary ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: viewFieldSummary,\n        shortcut: \"Ctrl+Shift+F\",\n      },\n      reset_view: {\n        function: resetView,\n        shortcut: \"Enter/Return\",\n      },\n      show_comments: {\n        state: settings.showComments ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: () =>\n          setSettings((prev) => ({\n            ...prev,\n            showComments: !prev.showComments,\n          })),\n      },\n      show_datatype: {\n        state: settings.showDataTypes ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: () =>\n          setSettings((prev) => ({\n            ...prev,\n            showDataTypes: !prev.showDataTypes,\n          })),\n      },\n      show_grid: {\n        state: settings.showGrid ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: viewGrid,\n        shortcut: \"Ctrl+Shift+G\",\n      },\n      snap_to_grid: {\n        state: settings.snapToGrid ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: snapToGrid,\n      },\n      show_cardinality: {\n        state: settings.showCardinality ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: () =>\n          setSettings((prev) => ({\n            ...prev,\n            showCardinality: !prev.showCardinality,\n          })),\n      },\n      show_relationship_labels: {\n        state: settings.showRelationshipLabels ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: () =>\n          setSettings((prev) => ({\n            ...prev,\n            showRelationshipLabels: !prev.showRelationshipLabels,\n          })),\n      },\n      show_debug_coordinates: {\n        state: settings.showDebugCoordinates ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: () =>\n          setSettings((prev) => ({\n            ...prev,\n            showDebugCoordinates: !prev.showDebugCoordinates,\n          })),\n      },\n      theme: {\n        children: [\n          {\n            name: t(\"light\"),\n            function: () => setSettings((prev) => ({ ...prev, mode: \"light\" })),\n          },\n          {\n            name: t(\"dark\"),\n            function: () => setSettings((prev) => ({ ...prev, mode: \"dark\" })),\n          },\n        ],\n        function: () => {},\n      },\n      zoom_in: {\n        function: zoomIn,\n        shortcut: \"Ctrl+(Up/Wheel)\",\n      },\n      zoom_out: {\n        function: zoomOut,\n        shortcut: \"Ctrl+(Down/Wheel)\",\n      },\n      fullscreen: {\n        state: fullscreen ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: fullscreen ? exitFullscreen : enterFullscreen,\n      },\n    },\n    settings: {\n      show_timeline: {\n        function: () => setSidesheet(SIDESHEET.TIMELINE),\n      },\n      autosave: {\n        state: settings.autosave ? (\n          <i className=\"bi bi-toggle-on\" />\n        ) : (\n          <i className=\"bi bi-toggle-off\" />\n        ),\n        function: () =>\n          setSettings((prev) => ({ ...prev, autosave: !prev.autosave })),\n      },\n      table_width: {\n        function: () => setModal(MODAL.TABLE_WIDTH),\n        disabled: layout.readOnly,\n      },\n      language: {\n        function: () => setModal(MODAL.LANGUAGE),\n      },\n      export_saved_data: {\n        function: exportSavedData,\n      },\n      clear_cache: {\n        function: () => {\n          deleteFromCache(gistId);\n          Toast.success(t(\"cache_cleared\"));\n        },\n      },\n      flush_storage: {\n        warning: {\n          title: t(\"flush_storage\"),\n          message: t(\"are_you_sure_flush_storage\"),\n        },\n        function: async () => {\n          localStorage.removeItem(STORAGE_KEY);\n          db.delete()\n            .then(() => {\n              Toast.success(t(\"storage_flushed\"));\n              navigate(\"/editor\", { replace: true });\n              window.location.reload();\n            })\n            .catch(() => {\n              Toast.error(t(\"oops_smth_went_wrong\"));\n            });\n        },\n      },\n    },\n    help: {\n      docs: {\n        function: () => window.open(`${socials.docs}`, \"_blank\"),\n        shortcut: \"Ctrl+H\",\n      },\n      shortcuts: {\n        function: () => window.open(`${socials.docs}/shortcuts`, \"_blank\"),\n      },\n      ask_on_discord: {\n        function: () => window.open(socials.discord, \"_blank\"),\n      },\n      report_bug: {\n        function: () => window.open(\"/bug-report\", \"_blank\"),\n      },\n    },\n  };\n\n  useHotkeys(\"mod+i\", fileImport, { preventDefault: true });\n  useHotkeys(\"mod+z\", undo, { preventDefault: true });\n  useHotkeys(\"mod+y\", redo, { preventDefault: true });\n  useHotkeys(\"mod+s\", save, { preventDefault: true });\n  useHotkeys(\"mod+o\", open, { preventDefault: true });\n  useHotkeys(\"mod+e\", edit, { preventDefault: true });\n  useHotkeys(\"mod+d\", duplicate, { preventDefault: true });\n  useHotkeys(\"mod+c\", copy, { preventDefault: true });\n  useHotkeys(\"mod+v\", paste, { preventDefault: true });\n  useHotkeys(\"mod+x\", cut, { preventDefault: true });\n  useHotkeys(\"delete\", del, { preventDefault: true });\n  useHotkeys(\"mod+shift+g\", viewGrid, { preventDefault: true });\n  useHotkeys(\"mod+up\", zoomIn, { preventDefault: true });\n  useHotkeys(\"mod+down\", zoomOut, { preventDefault: true });\n  useHotkeys(\"mod+shift+m\", viewStrictMode, {\n    preventDefault: true,\n  });\n  useHotkeys(\"mod+shift+f\", viewFieldSummary, {\n    preventDefault: true,\n  });\n  useHotkeys(\"mod+shift+s\", saveDiagramAs, {\n    preventDefault: true,\n  });\n  useHotkeys(\"mod+alt+c\", copyAsImage, { preventDefault: true });\n  useHotkeys(\"enter\", resetView, { preventDefault: true });\n  useHotkeys(\"mod+h\", () => window.open(socials.docs, \"_blank\"), {\n    preventDefault: true,\n  });\n  useHotkeys(\"mod+alt+w\", fitWindow, { preventDefault: true });\n  useHotkeys(\"alt+e\", toggleDBMLEditor, { preventDefault: true });\n\n  return (\n    <>\n      <div>\n        {layout.header && (\n          <div\n            className=\"flex justify-between items-center me-7\"\n            style={isRtl(i18n.language) ? { direction: \"rtl\" } : {}}\n          >\n            {header()}\n            {!isTemplate && (\n              <Button\n                type=\"primary\"\n                className=\"!text-base me-2 !pe-6 !ps-5 !py-[18px] !rounded-md\"\n                size=\"default\"\n                icon={<IconShareStroked />}\n                onClick={() => setModal(MODAL.SHARE)}\n              >\n                {t(\"share\")}\n              </Button>\n            )}\n          </div>\n        )}\n        {layout.toolbar && toolbar()}\n      </div>\n      <Modal\n        modal={modal}\n        exportData={exportData}\n        setExportData={setExportData}\n        title={title}\n        setTitle={setTitle}\n        setModal={setModal}\n        importFrom={importFrom}\n        importDb={importDb}\n      />\n      <Sidesheet\n        type={sidesheet}\n        title={title}\n        setTitle={setTitle}\n        onClose={() => setSidesheet(SIDESHEET.NONE)}\n      />\n    </>\n  );\n\n  function toolbar() {\n    return (\n      <div\n        className=\"py-1.5 px-5 flex justify-between items-center rounded-xl my-1 sm:mx-1 xl:mx-6 select-none overflow-hidden toolbar-theme\"\n        style={isRtl(i18n.language) ? { direction: \"rtl\" } : {}}\n      >\n        <div className=\"flex justify-start items-center\">\n          <LayoutDropdown />\n          <Divider layout=\"vertical\" margin=\"8px\" />\n          <Tooltip content={t(\"zoom_out\")} position=\"bottom\">\n            <button\n              className=\"py-1 px-2 hover-2 rounded-sm text-lg\"\n              onClick={() =>\n                setTransform((prev) => ({ ...prev, zoom: prev.zoom / 1.2 }))\n              }\n            >\n              <i className=\"fa-solid fa-magnifying-glass-minus\" />\n            </button>\n          </Tooltip>\n          <Dropdown\n            style={{ width: \"240px\" }}\n            position={isRtl(i18n.language) ? \"bottomRight\" : \"bottomLeft\"}\n            render={\n              <Dropdown.Menu\n                style={isRtl(i18n.language) ? { direction: \"rtl\" } : {}}\n              >\n                <Dropdown.Item\n                  onClick={fitWindow}\n                  style={{ display: \"flex\", justifyContent: \"space-between\" }}\n                >\n                  <div>{t(\"fit_window_reset\")}</div>\n                  <div className=\"text-gray-400\">Ctrl+Alt+W</div>\n                </Dropdown.Item>\n                <Dropdown.Divider />\n                {[0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 3.0].map((e, i) => (\n                  <Dropdown.Item\n                    key={i}\n                    onClick={() => {\n                      setTransform((prev) => ({ ...prev, zoom: e }));\n                    }}\n                  >\n                    {Math.floor(e * 100)}%\n                  </Dropdown.Item>\n                ))}\n                <Dropdown.Divider />\n                <Dropdown.Item>\n                  <InputNumber\n                    field=\"zoom\"\n                    label={t(\"zoom\")}\n                    placeholder={t(\"zoom\")}\n                    suffix={<div className=\"p-1\">%</div>}\n                    onChange={(v) =>\n                      setTransform((prev) => ({\n                        ...prev,\n                        zoom: parseFloat(v) * 0.01,\n                      }))\n                    }\n                  />\n                </Dropdown.Item>\n              </Dropdown.Menu>\n            }\n            trigger=\"click\"\n          >\n            <div className=\"py-1 px-2 hover-2 rounded-sm flex items-center justify-center\">\n              <div className=\"w-[40px]\">\n                {Math.floor(transform.zoom * 100)}%\n              </div>\n              <div>\n                <IconCaretdown />\n              </div>\n            </div>\n          </Dropdown>\n          <Tooltip content={t(\"zoom_in\")} position=\"bottom\">\n            <button\n              className=\"py-1 px-2 hover-2 rounded-sm text-lg\"\n              onClick={() =>\n                setTransform((prev) => ({ ...prev, zoom: prev.zoom * 1.2 }))\n              }\n            >\n              <i className=\"fa-solid fa-magnifying-glass-plus\" />\n            </button>\n          </Tooltip>\n          <Divider layout=\"vertical\" margin=\"8px\" />\n          <Tooltip content={t(\"undo\")} position=\"bottom\">\n            <button\n              className=\"py-1 px-2 hover-2 rounded-sm flex items-center disabled:opacity-50\"\n              disabled={undoStack.length === 0 || layout.readOnly}\n              onClick={undo}\n            >\n              <IconUndo size=\"large\" />\n            </button>\n          </Tooltip>\n          <Tooltip content={t(\"redo\")} position=\"bottom\">\n            <button\n              className=\"py-1 px-2 hover-2 rounded-sm flex items-center disabled:opacity-50\"\n              disabled={redoStack.length === 0 || layout.readOnly}\n              onClick={redo}\n            >\n              <IconRedo size=\"large\" />\n            </button>\n          </Tooltip>\n          <Divider layout=\"vertical\" margin=\"8px\" />\n          <Tooltip content={t(\"add_table\")} position=\"bottom\">\n            <button\n              className=\"flex items-center py-1 px-2 hover-2 rounded-sm disabled:opacity-50\"\n              onClick={() => addTable()}\n              disabled={layout.readOnly}\n            >\n              <IconAddTable />\n            </button>\n          </Tooltip>\n          <Tooltip content={t(\"add_area\")} position=\"bottom\">\n            <button\n              className=\"py-1 px-2 hover-2 rounded-sm flex items-center disabled:opacity-50\"\n              onClick={() => addArea()}\n              disabled={layout.readOnly}\n            >\n              <IconAddArea />\n            </button>\n          </Tooltip>\n          <Tooltip content={t(\"add_note\")} position=\"bottom\">\n            <button\n              className=\"py-1 px-2 hover-2 rounded-sm flex items-center disabled:opacity-50\"\n              onClick={() => addNote()}\n              disabled={layout.readOnly}\n            >\n              <IconAddNote />\n            </button>\n          </Tooltip>\n          <Divider layout=\"vertical\" margin=\"8px\" />\n          <Tooltip content={t(\"save\")} position=\"bottom\">\n            <button\n              className=\"py-1 px-2 hover-2 rounded-sm flex items-center disabled:opacity-50\"\n              onClick={save}\n              disabled={layout.readOnly}\n            >\n              <IconSaveStroked size=\"extra-large\" />\n            </button>\n          </Tooltip>\n          <Divider layout=\"vertical\" margin=\"8px\" />\n          <Tooltip content={t(\"versions\")} position=\"bottom\">\n            <button\n              className=\"py-1 px-2 hover-2 rounded-sm text-xl -mt-0.5\"\n              onClick={() => setSidesheet(SIDESHEET.VERSIONS)}\n            >\n              <i className=\"fa-solid fa-code-branch\" />\n            </button>\n          </Tooltip>\n          <Divider layout=\"vertical\" margin=\"8px\" />\n          <Tooltip content={t(\"theme\")} position=\"bottom\">\n            <button\n              className=\"py-1 px-2 hover-2 rounded-sm text-xl -mt-0.5\"\n              onClick={() => {\n                const body = document.body;\n                if (body.hasAttribute(\"theme-mode\")) {\n                  if (body.getAttribute(\"theme-mode\") === \"light\") {\n                    menu[\"view\"][\"theme\"].children[1].function();\n                  } else {\n                    menu[\"view\"][\"theme\"].children[0].function();\n                  }\n                }\n              }}\n            >\n              <i className=\"fa-solid fa-circle-half-stroke\" />\n            </button>\n          </Tooltip>\n        </div>\n        <button\n          onClick={() => invertLayout(\"header\")}\n          className=\"flex items-center\"\n        >\n          {layout.header ? <IconChevronUp /> : <IconChevronDown />}\n        </button>\n      </div>\n    );\n  }\n\n  function getState() {\n    switch (saveState) {\n      case State.NONE:\n        return t(\"no_changes\");\n      case State.LOADING:\n        return t(\"loading\");\n      case State.SAVED:\n        return `${t(\"last_saved\")} ${lastSaved}`;\n      case State.SAVING:\n        return t(\"saving\");\n      case State.ERROR:\n        return t(\"failed_to_save\");\n      case State.FAILED_TO_LOAD:\n        return t(\"failed_to_load\");\n      default:\n        return \"\";\n    }\n  }\n\n  function header() {\n    return (\n      <nav\n        className=\"flex justify-between pt-1 items-center whitespace-nowrap\"\n        style={isRtl(i18n.language) ? { direction: \"rtl\" } : {}}\n      >\n        <div className=\"flex justify-start items-center\">\n          <Link to=\"/\">\n            <img\n              width={54}\n              src={icon}\n              alt=\"logo\"\n              className=\"ms-7 min-w-[54px]\"\n            />\n          </Link>\n          <div className=\"ms-1 mt-1\">\n            <div className=\"flex items-center ms-3 gap-2\">\n              {databases[database].image && (\n                <img\n                  src={databases[database].image}\n                  className=\"h-5\"\n                  style={{\n                    filter:\n                      \"opacity(0.4) drop-shadow(0 0 0 white) drop-shadow(0 0 0 white)\",\n                  }}\n                  alt={databases[database].name + \" icon\"}\n                  title={databases[database].name + \" diagram\"}\n                />\n              )}\n              <div\n                className=\"text-xl flex items-center gap-1 me-1\"\n                onPointerEnter={(e) => e.isPrimary && setShowEditName(true)}\n                onPointerLeave={(e) => e.isPrimary && setShowEditName(false)}\n                onPointerDown={(e) => {\n                  // Required for onPointerLeave to trigger when a touch pointer leaves\n                  // https://stackoverflow.com/a/70976017/1137077\n                  e.target.releasePointerCapture(e.pointerId);\n                }}\n                onClick={!layout.readOnly && (() => setModal(MODAL.RENAME))}\n              >\n                <span>{(isTemplate ? \"Templates/\" : \"Diagrams/\") + title}</span>\n                {version && (\n                  <Tag className=\"mt-1\" color=\"blue\" size=\"small\">\n                    {version.substring(0, 7)}\n                  </Tag>\n                )}\n              </div>\n              {(showEditName || modal === MODAL.RENAME) && !layout.readOnly && (\n                <IconEdit />\n              )}\n            </div>\n            <div className=\"flex items-center\">\n              <div className=\"flex justify-start text-md select-none me-2\">\n                {Object.keys(menu).map((category) => (\n                  <Dropdown\n                    key={category}\n                    position=\"bottomLeft\"\n                    style={{\n                      width: \"240px\",\n                      direction: isRtl(i18n.language) ? \"rtl\" : \"ltr\",\n                    }}\n                    render={\n                      <Dropdown.Menu className=\"menu max-h-[calc(100vh-80px)] overflow-auto\">\n                        {Object.keys(menu[category]).map((item, index) => {\n                          if (menu[category][item].children) {\n                            return (\n                              <Dropdown\n                                className=\"min-w-36 max-w-72\"\n                                key={item}\n                                position=\"rightTop\"\n                                render={\n                                  <Dropdown.Menu>\n                                    {menu[category][item].children.map(\n                                      (e, i) => {\n                                        if (e.divider) {\n                                          return (\n                                            <Dropdown.Divider\n                                              key={`divider-${i}`}\n                                            />\n                                          );\n                                        }\n                                        return (\n                                          <Dropdown.Item\n                                            key={i}\n                                            onClick={e.function}\n                                            className=\"flex w-full items-center justify-between gap-1\"\n                                            disabled={e.disabled}\n                                          >\n                                            <span className=\"truncate flex-1 min-w-0\">\n                                              {e.name}\n                                            </span>\n                                            {e.label && (\n                                              <Tag\n                                                size=\"small\"\n                                                className=\"flex-shrink-0\"\n                                              >\n                                                {e.label}\n                                              </Tag>\n                                            )}\n                                          </Dropdown.Item>\n                                        );\n                                      },\n                                    )}\n                                  </Dropdown.Menu>\n                                }\n                              >\n                                <Dropdown.Item\n                                  style={{\n                                    display: \"flex\",\n                                    justifyContent: \"space-between\",\n                                    alignItems: \"center\",\n                                  }}\n                                  onClick={menu[category][item].function}\n                                >\n                                  {t(item)}\n\n                                  {isRtl(i18n.language) ? (\n                                    <IconChevronLeft />\n                                  ) : (\n                                    <IconChevronRight />\n                                  )}\n                                </Dropdown.Item>\n                              </Dropdown>\n                            );\n                          }\n                          if (\n                            menu[category][item].warning &&\n                            !menu[category][item].disabled\n                          ) {\n                            return (\n                              <Popconfirm\n                                key={index}\n                                title={menu[category][item].warning.title}\n                                content={menu[category][item].warning.message}\n                                onConfirm={menu[category][item].function}\n                                position=\"right\"\n                                okText={t(\"confirm\")}\n                                cancelText={t(\"cancel\")}\n                              >\n                                <Dropdown.Item>{t(item)}</Dropdown.Item>\n                              </Popconfirm>\n                            );\n                          }\n                          return (\n                            <Dropdown.Item\n                              key={index}\n                              disabled={menu[category][item].disabled}\n                              onClick={menu[category][item].function}\n                              style={\n                                menu[category][item].shortcut && {\n                                  display: \"flex\",\n                                  justifyContent: \"space-between\",\n                                  alignItems: \"center\",\n                                }\n                              }\n                            >\n                              <div className=\"w-full flex items-center justify-between\">\n                                <div>{t(item)}</div>\n                                <div className=\"flex items-center gap-1\">\n                                  {menu[category][item].shortcut && (\n                                    <div className=\"text-gray-400\">\n                                      {menu[category][item].shortcut}\n                                    </div>\n                                  )}\n                                  {menu[category][item].state &&\n                                    menu[category][item].state}\n                                </div>\n                              </div>\n                            </Dropdown.Item>\n                          );\n                        })}\n                      </Dropdown.Menu>\n                    }\n                  >\n                    <div className=\"px-3 py-1 hover-2 rounded-sm\">\n                      {t(category)}\n                    </div>\n                  </Dropdown>\n                ))}\n              </div>\n              {layout.readOnly && <Tag size=\"small\">{t(\"read_only\")}</Tag>}\n              {!layout.readOnly && (\n                <Tag\n                  size=\"small\"\n                  type=\"light\"\n                  prefixIcon={\n                    saveState === State.LOADING ||\n                    saveState === State.SAVING ? (\n                      <Spin size=\"small\" />\n                    ) : null\n                  }\n                >\n                  {getState()}\n                </Tag>\n              )}\n            </div>\n          </div>\n        </div>\n      </nav>\n    );\n  }\n}\n"
  },
  {
    "path": "src/components/EditorHeader/LayoutDropdown.jsx",
    "content": "import {\n  IconCaretdown,\n  IconCheckboxTick,\n  IconRowsStroked,\n} from \"@douyinfe/semi-icons\";\nimport { Dropdown } from \"@douyinfe/semi-ui\";\nimport { useFullscreen, useLayout } from \"../../hooks\";\nimport { enterFullscreen, exitFullscreen } from \"../../utils/fullscreen\";\nimport { useTranslation } from \"react-i18next\";\nimport { isRtl } from \"../../i18n/utils/rtl\";\nimport i18n from \"../../i18n/i18n\";\n\nexport default function LayoutDropdown() {\n  const fullscreen = useFullscreen();\n  const { layout, setLayout } = useLayout();\n  const { t } = useTranslation();\n\n  const invertLayout = (component) =>\n    setLayout((prev) => ({ ...prev, [component]: !prev[component] }));\n\n  return (\n    <Dropdown\n      position=\"bottomLeft\"\n      style={{\n        width: \"180px\",\n        direction: isRtl(i18n.language) ? \"rtl\" : \"ltr\",\n      }}\n      render={\n        <Dropdown.Menu>\n          <Dropdown.Item\n            icon={\n              layout.header ? <IconCheckboxTick /> : <div className=\"px-2\" />\n            }\n            onClick={() => invertLayout(\"header\")}\n          >\n            {t(\"header\")}\n          </Dropdown.Item>\n          <Dropdown.Item\n            icon={\n              layout.sidebar ? <IconCheckboxTick /> : <div className=\"px-2\" />\n            }\n            onClick={() => invertLayout(\"sidebar\")}\n          >\n            {t(\"sidebar\")}\n          </Dropdown.Item>\n          <Dropdown.Item\n            icon={\n              layout.issues ? <IconCheckboxTick /> : <div className=\"px-2\" />\n            }\n            onClick={() => invertLayout(\"issues\")}\n          >\n            {t(\"issues\")}\n          </Dropdown.Item>\n          <Dropdown.Divider />\n          <Dropdown.Item\n            icon={fullscreen ? <IconCheckboxTick /> : <div className=\"px-2\" />}\n            onClick={() => {\n              if (fullscreen) {\n                exitFullscreen();\n              } else {\n                enterFullscreen();\n              }\n            }}\n          >\n            {t(\"fullscreen\")}\n          </Dropdown.Item>\n        </Dropdown.Menu>\n      }\n      trigger=\"click\"\n    >\n      <div className=\"py-1 px-2 hover-2 rounded-sm flex items-center justify-center\">\n        <IconRowsStroked size=\"extra-large\" />\n        <div>\n          <IconCaretdown />\n        </div>\n      </div>\n    </Dropdown>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/Modal/ImportDiagram.jsx",
    "content": "import {\n  ddbDiagramIsValid,\n  jsonDiagramIsValid,\n} from \"../../../utils/validateSchema\";\nimport { Upload, Banner } from \"@douyinfe/semi-ui\";\nimport { DB, IMPORT_FROM, STATUS } from \"../../../data/constants\";\nimport {\n  useAreas,\n  useEnums,\n  useNotes,\n  useDiagram,\n  useTypes,\n} from \"../../../hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport { fromDBML } from \"../../../utils/importFrom/dbml\";\n\nexport default function ImportDiagram({\n  setImportData,\n  error,\n  setError,\n  importFrom,\n}) {\n  const { areas } = useAreas();\n  const { notes } = useNotes();\n  const { tables, relationships, database } = useDiagram();\n  const { types } = useTypes();\n  const { enums } = useEnums();\n  const { t } = useTranslation();\n\n  const diagramIsEmpty = () => {\n    return (\n      tables.length === 0 &&\n      relationships.length === 0 &&\n      notes.length === 0 &&\n      areas.length === 0 &&\n      types.length === 0 &&\n      enums.length === 0\n    );\n  };\n\n  const loadJsonData = (file, e) => {\n    let jsonObject = null;\n    try {\n      jsonObject = JSON.parse(e.target.result);\n    } catch (error) {\n      setError({\n        type: STATUS.ERROR,\n        message: \"The file contains an error.\",\n      });\n      return;\n    }\n\n    if (file.type === \"application/json\") {\n      if (!jsonDiagramIsValid(jsonObject)) {\n        setError({\n          type: STATUS.ERROR,\n          message: \"The file is missing necessary properties for a diagram.\",\n        });\n        return;\n      }\n    } else if (file.name.split(\".\").pop() === \"ddb\") {\n      if (!ddbDiagramIsValid(jsonObject)) {\n        setError({\n          type: STATUS.ERROR,\n          message: \"The file is missing necessary properties for a diagram.\",\n        });\n        return;\n      }\n    }\n\n    if (!jsonObject.database) {\n      jsonObject.database = DB.GENERIC;\n    }\n\n    if (jsonObject.database !== database) {\n      setError({\n        type: STATUS.ERROR,\n        message:\n          \"The imported diagram and the open diagram don't use matching databases.\",\n      });\n      return;\n    }\n\n    let ok = true;\n    jsonObject.relationships.forEach((rel) => {\n      const startTable = jsonObject.tables.find(\n        (t) => t.id === rel.startTableId,\n      );\n      const endTable = jsonObject.tables.find((t) => t.id === rel.endTableId);\n\n      if (!startTable || !endTable) {\n        setError({\n          type: STATUS.ERROR,\n          message: `Relationship ${rel.name} references a table that does not exist.`,\n        });\n        ok = false;\n        return;\n      }\n\n      if (\n        !startTable.fields.find((f) => f.id === rel.startFieldId) ||\n        !endTable.fields.find((f) => f.id === rel.endFieldId)\n      ) {\n        setError({\n          type: STATUS.ERROR,\n          message: `Relationship ${rel.name} references a field that does not exist.`,\n        });\n        ok = false;\n        return;\n      }\n    });\n\n    if (!ok) return;\n\n    setImportData(jsonObject);\n    if (diagramIsEmpty()) {\n      setError({\n        type: STATUS.OK,\n        message: \"Everything looks good. You can now import.\",\n      });\n    } else {\n      setError({\n        type: STATUS.WARNING,\n        message:\n          \"The current diagram is not empty. Importing a new diagram will overwrite the current changes.\",\n      });\n    }\n  };\n\n  const loadDBMLData = (e) => {\n    try {\n      setImportData(fromDBML(e.target.result));\n    } catch (error) {\n      const message = `${error.diags[0].name} [Ln ${error.diags[0].location.start.line}, Col ${error.diags[0].location.start.column}]: ${error.diags[0].message}`;\n\n      setError({ type: STATUS.ERROR, message });\n    }\n  };\n\n  const getAcceptableFileTypes = () => {\n    switch (importFrom) {\n      case IMPORT_FROM.JSON:\n        return \"application/json,.ddb\";\n      case IMPORT_FROM.DBML:\n        return \".dbml\";\n      default:\n        return \"\";\n    }\n  };\n\n  const getDragSubText = () => {\n    switch (importFrom) {\n      case IMPORT_FROM.JSON:\n        return `${t(\"supported_types\")} JSON, DDB`;\n      case IMPORT_FROM.DBML:\n        return `${t(\"supported_types\")} DBML`;\n      default:\n        return \"\";\n    }\n  };\n\n  return (\n    <div>\n      <Upload\n        action=\"#\"\n        beforeUpload={({ file, fileList }) => {\n          const f = fileList[0].fileInstance;\n          if (!f) {\n            return;\n          }\n          const reader = new FileReader();\n          reader.onload = async (e) => {\n            if (importFrom == IMPORT_FROM.JSON) loadJsonData(f, e);\n            if (importFrom == IMPORT_FROM.DBML) loadDBMLData(e);\n          };\n          reader.readAsText(f);\n\n          return {\n            autoRemove: false,\n            fileInstance: file.fileInstance,\n            status: \"success\",\n            shouldUpload: false,\n          };\n        }}\n        draggable={true}\n        dragMainText={t(\"drag_and_drop_files\")}\n        dragSubText={getDragSubText()}\n        accept={getAcceptableFileTypes()}\n        onRemove={() =>\n          setError({\n            type: STATUS.NONE,\n            message: \"\",\n          })\n        }\n        onFileChange={() =>\n          setError({\n            type: STATUS.NONE,\n            message: \"\",\n          })\n        }\n        limit={1}\n      />\n      {error.type === STATUS.ERROR ? (\n        <Banner\n          type=\"danger\"\n          fullMode={false}\n          description={<div>{error.message}</div>}\n        />\n      ) : error.type === STATUS.OK ? (\n        <Banner\n          type=\"info\"\n          fullMode={false}\n          description={<div>{error.message}</div>}\n        />\n      ) : (\n        error.type === STATUS.WARNING && (\n          <Banner\n            type=\"warning\"\n            fullMode={false}\n            description={<div>{error.message}</div>}\n          />\n        )\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/Modal/ImportSource.jsx",
    "content": "import { Upload, Checkbox, Banner, Tabs, TabPane } from \"@douyinfe/semi-ui\";\nimport { STATUS } from \"../../../data/constants\";\nimport { useTranslation } from \"react-i18next\";\nimport CodeEditor from \"../../CodeEditor\";\n\nexport default function ImportSource({\n  importData,\n  setImportData,\n  error,\n  setError,\n}) {\n  const { t } = useTranslation();\n\n  return (\n    <div>\n      <Tabs>\n        <TabPane tab={t(\"insert_sql\")} itemKey=\"text-import\">\n          <CodeEditor\n            height={224}\n            language=\"sql\"\n            onChange={(value) => {\n              setImportData((prev) => ({ ...prev, src: value }));\n              setError({\n                type: STATUS.NONE,\n                message: \"\",\n              });\n            }}\n          />\n        </TabPane>\n        <TabPane tab={t(\"upload_file\")} itemKey=\"file-import\">\n          <Upload\n            action=\"#\"\n            beforeUpload={({ file, fileList }) => {\n              const f = fileList[0].fileInstance;\n              if (!f) {\n                return;\n              }\n              const reader = new FileReader();\n              reader.onload = async (e) => {\n                setImportData((prev) => ({ ...prev, src: e.target.result }));\n              };\n              reader.readAsText(f);\n\n              return {\n                autoRemove: false,\n                fileInstance: file.fileInstance,\n                status: \"success\",\n                shouldUpload: false,\n              };\n            }}\n            draggable={true}\n            dragMainText={t(\"drag_and_drop_files\")}\n            dragSubText={t(\"upload_sql_to_generate_diagrams\")}\n            accept=\".sql\"\n            onRemove={() => {\n              setError({\n                type: STATUS.NONE,\n                message: \"\",\n              });\n              setImportData((prev) => ({ ...prev, src: \"\" }));\n            }}\n            onFileChange={() =>\n              setError({\n                type: STATUS.NONE,\n                message: \"\",\n              })\n            }\n            limit={1}\n          />\n        </TabPane>\n      </Tabs>\n\n      <div className=\"mt-2\">\n        <Checkbox\n          aria-label=\"overwrite checkbox\"\n          checked={importData.overwrite}\n          onChange={(e) =>\n            setImportData((prev) => ({\n              ...prev,\n              overwrite: e.target.checked,\n            }))\n          }\n        >\n          {t(\"overwrite_existing_diagram\")}\n        </Checkbox>\n        <div className=\"mt-2\">\n          {error.type === STATUS.ERROR ? (\n            <Banner\n              type=\"danger\"\n              fullMode={false}\n              description={<div>{error.message}</div>}\n            />\n          ) : error.type === STATUS.OK ? (\n            <Banner\n              type=\"info\"\n              fullMode={false}\n              description={<div>{error.message}</div>}\n            />\n          ) : (\n            error.type === STATUS.WARNING && (\n              <Banner\n                type=\"warning\"\n                fullMode={false}\n                description={<div>{error.message}</div>}\n              />\n            )\n          )}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/Modal/Language.jsx",
    "content": "import { useSettings } from \"../../../hooks\";\nimport { languages } from \"../../../i18n/i18n\";\n\nexport default function Language({ language, setLanguage }) {\n  const { settings } = useSettings();\n  const isDarkMode = settings.mode === \"dark\";\n\n  return (\n    <div className=\"grid grid-cols-4 md:grid-cols-2 gap-4\">\n      {languages.map((l) => (\n        <button\n          key={l.code}\n          onClick={() => setLanguage(l.code)}\n          className={`space-y-1 py-3 px-4 rounded-md border-2 ${\n            isDarkMode\n              ? \"bg-zinc-700 hover:bg-zinc-600\"\n              : \"bg-zinc-100 hover:bg-zinc-200\"\n          } ${language === l.code ? \"border-zinc-400\" : \"border-transparent\"}`}\n        >\n          <div className=\"flex justify-between items-center\">\n            <div className=\"font-semibold\">{l.native_name}</div>\n            <div className=\"opacity-60\">{l.code}</div>\n          </div>\n          <div className=\"text-start\">{l.name}</div>\n        </button>\n      ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/Modal/Modal.jsx",
    "content": "import { Image, Input, Modal as SemiUIModal, Spin } from \"@douyinfe/semi-ui\";\nimport { saveAs } from \"file-saver\";\nimport { Parser } from \"node-sql-parser\";\nimport { Parser as OracleParser } from \"oracle-sql-parser\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { DB, MODAL, STATUS } from \"../../../data/constants\";\nimport { databases } from \"../../../data/databases\";\nimport {\n  useAreas,\n  useDiagram,\n  useEnums,\n  useNotes,\n  useSettings,\n  useTransform,\n  useTypes,\n  useUndoRedo,\n} from \"../../../hooks\";\nimport { isRtl } from \"../../../i18n/utils/rtl\";\nimport { importSQL } from \"../../../utils/importSQL\";\nimport {\n  getModalTitle,\n  getModalWidth,\n  getOkText,\n} from \"../../../utils/modalData\";\nimport CodeEditor from \"../../CodeEditor\";\nimport ImportDiagram from \"./ImportDiagram\";\nimport ImportSource from \"./ImportSource\";\nimport Language from \"./Language\";\nimport New from \"./New\";\nimport Open from \"./Open\";\nimport Rename from \"./Rename\";\nimport SetTableWidth from \"./SetTableWidth\";\nimport Share from \"./Share\";\nimport { useNavigate } from \"react-router-dom\";\n\nconst extensionToLanguage = {\n  md: \"markdown\",\n  sql: \"sql\",\n  dbml: \"dbml\",\n  json: \"json\",\n};\n\nexport default function Modal({\n  modal,\n  setModal,\n  title,\n  setTitle,\n  exportData,\n  setExportData,\n  importDb,\n  importFrom,\n}) {\n  const { t, i18n } = useTranslation();\n  const { setTables, setRelationships, database } = useDiagram();\n  const { setNotes } = useNotes();\n  const { setAreas } = useAreas();\n  const { setTypes } = useTypes();\n  const { setEnums } = useEnums();\n  const { setTransform } = useTransform();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const { settings, setSettings } = useSettings();\n  const [uncontrolledTitle, setUncontrolledTitle] = useState(title);\n  const [uncontrolledLanguage, setUncontrolledLanguage] = useState(\n    i18n.language,\n  );\n  const [tempTableWidth, setTempTableWidth] = useState(settings.tableWidth);\n  const [importSource, setImportSource] = useState({\n    src: \"\",\n    overwrite: false,\n  });\n  const [importData, setImportData] = useState(null);\n  const [error, setError] = useState({\n    type: STATUS.NONE,\n    message: \"\",\n  });\n  const [selectedTemplateId, setSelectedTemplateId] = useState(-1);\n  const [selectedDiagramId, setSelectedDiagramId] = useState(0);\n  const [saveAsTitle, setSaveAsTitle] = useState(title);\n  const navigate = useNavigate();\n\n  const overwriteDiagram = () => {\n    setTables(importData.tables);\n    setRelationships(importData.relationships);\n    setAreas(importData.subjectAreas ?? []);\n    setNotes(importData.notes ?? []);\n    if (importData.title) {\n      setTitle(importData.title);\n    }\n    if (databases[database].hasEnums && importData.enums) {\n      setEnums(importData.enums);\n    }\n    if (databases[database].hasTypes && importData.types) {\n      setTypes(importData.types);\n    }\n  };\n\n  const parseSQLAndLoadDiagram = () => {\n    const targetDatabase = database === DB.GENERIC ? importDb : database;\n\n    let ast = null;\n    try {\n      if (targetDatabase === DB.ORACLESQL) {\n        const oracleParser = new OracleParser();\n\n        ast = oracleParser.parse(importSource.src);\n      } else {\n        const parser = new Parser();\n\n        ast = parser.astify(importSource.src, {\n          database: targetDatabase,\n        });\n      }\n    } catch (error) {\n      const message = error.location\n        ? `${error.name} [Ln ${error.location.start.line}, Col ${error.location.start.column}]: ${error.message}`\n        : error.message;\n\n      setError({ type: STATUS.ERROR, message });\n      return;\n    }\n\n    try {\n      const diagramData = importSQL(\n        ast,\n        database === DB.GENERIC ? importDb : database,\n        database,\n      );\n\n      if (importSource.overwrite) {\n        setTables(diagramData.tables);\n        setRelationships(diagramData.relationships);\n        if (databases[database].hasTypes) setTypes(diagramData.types ?? []);\n        if (databases[database].hasEnums) setEnums(diagramData.enums ?? []);\n        setTransform((prev) => ({ ...prev, pan: { x: 0, y: 0 } }));\n        setNotes([]);\n        setAreas([]);\n      } else {\n        setTables((prev) => [...prev, ...diagramData.tables]);\n        setRelationships((prev) =>\n          [...prev, ...diagramData.relationships].map((r, i) => ({\n            ...r,\n            id: i,\n          })),\n        );\n        if (databases[database].hasTypes && diagramData.types.length)\n          setTypes((prev) => [...prev, ...diagramData.types]);\n        if (databases[database].hasEnums && diagramData.enums.length)\n          setEnums((prev) => [...prev, ...diagramData.enums]);\n      }\n\n      setUndoStack([]);\n      setRedoStack([]);\n\n      setModal(MODAL.NONE);\n    } catch (e) {\n      setError({\n        type: STATUS.ERROR,\n        message: `Please check for syntax errors or let us know about the error.`,\n      });\n    }\n  };\n\n  const getModalOnOk = async () => {\n    switch (modal) {\n      case MODAL.IMG:\n        saveAs(\n          exportData.data,\n          `${exportData.filename}.${exportData.extension}`,\n        );\n        return;\n      case MODAL.CODE: {\n        const blob = new Blob([exportData.data], {\n          type: \"application/json\",\n        });\n        saveAs(blob, `${exportData.filename}.${exportData.extension}`);\n        return;\n      }\n      case MODAL.IMPORT:\n        if (error.type !== STATUS.ERROR) {\n          setTransform((prev) => ({ ...prev, pan: { x: 0, y: 0 } }));\n          overwriteDiagram();\n          setImportData(null);\n          setModal(MODAL.NONE);\n          setUndoStack([]);\n          setRedoStack([]);\n        }\n        return;\n      case MODAL.IMPORT_SRC:\n        parseSQLAndLoadDiagram();\n        return;\n      case MODAL.OPEN:\n        if (!selectedDiagramId) return;\n        navigate(`/editor/diagrams/${selectedDiagramId}`, \"_blank\");\n        setModal(MODAL.NONE);\n        return;\n      case MODAL.RENAME:\n        setTitle(uncontrolledTitle);\n        setModal(MODAL.NONE);\n        return;\n      case MODAL.SAVEAS:\n        setTitle(saveAsTitle);\n        setModal(MODAL.NONE);\n        return;\n      case MODAL.NEW:\n        window.open(\"/editor/templates/\" + selectedTemplateId, \"_blank\");\n        setModal(MODAL.NONE);\n        return;\n      case MODAL.LANGUAGE:\n        i18n.changeLanguage(uncontrolledLanguage);\n        setModal(MODAL.NONE);\n        return;\n      case MODAL.TABLE_WIDTH:\n        setSettings((prev) => ({ ...prev, tableWidth: tempTableWidth }));\n        setModal(MODAL.NONE);\n        return;\n      default:\n        setModal(MODAL.NONE);\n        return;\n    }\n  };\n\n  const getModalBody = () => {\n    switch (modal) {\n      case MODAL.IMPORT:\n        return (\n          <ImportDiagram\n            setImportData={setImportData}\n            error={error}\n            setError={setError}\n            importFrom={importFrom}\n          />\n        );\n      case MODAL.IMPORT_SRC:\n        return (\n          <ImportSource\n            importData={importSource}\n            setImportData={setImportSource}\n            error={error}\n            setError={setError}\n          />\n        );\n      case MODAL.NEW:\n        return (\n          <New\n            selectedTemplateId={selectedTemplateId}\n            setSelectedTemplateId={setSelectedTemplateId}\n          />\n        );\n      case MODAL.RENAME:\n        return (\n          <Rename key={title} title={title} setTitle={setUncontrolledTitle} />\n        );\n      case MODAL.OPEN:\n        return (\n          <Open\n            selectedDiagramId={selectedDiagramId}\n            setSelectedDiagramId={setSelectedDiagramId}\n          />\n        );\n      case MODAL.SAVEAS:\n        return (\n          <Input\n            placeholder={t(\"name\")}\n            value={saveAsTitle}\n            onChange={(v) => setSaveAsTitle(v)}\n          />\n        );\n      case MODAL.CODE:\n      case MODAL.IMG:\n        if (exportData.data !== \"\" || exportData.data) {\n          return (\n            <>\n              {modal === MODAL.IMG ? (\n                <Image src={exportData.data} alt=\"Diagram\" height={280} />\n              ) : (\n                <CodeEditor\n                  height={360}\n                  value={exportData.data}\n                  language={extensionToLanguage[exportData.extension]}\n                  options={{ readOnly: true }}\n                  showCopyButton={true}\n                />\n              )}\n              <div className=\"text-sm font-semibold mt-2\">{t(\"filename\")}:</div>\n              <Input\n                value={exportData.filename}\n                placeholder={t(\"filename\")}\n                suffix={<div className=\"p-2\">{`.${exportData.extension}`}</div>}\n                onChange={(value) =>\n                  setExportData((prev) => ({ ...prev, filename: value }))\n                }\n                field=\"filename\"\n              />\n            </>\n          );\n        } else {\n          return (\n            <div className=\"text-center my-3 text-sky-600\">\n              <Spin tip={t(\"loading\")} size=\"large\" />\n            </div>\n          );\n        }\n      case MODAL.TABLE_WIDTH:\n        return (\n          <SetTableWidth\n            tempWidth={tempTableWidth}\n            setTempWidth={setTempTableWidth}\n          />\n        );\n      case MODAL.LANGUAGE:\n        return (\n          <Language\n            language={uncontrolledLanguage}\n            setLanguage={setUncontrolledLanguage}\n          />\n        );\n      case MODAL.SHARE:\n        return <Share title={title} setModal={setModal} />;\n      default:\n        return <></>;\n    }\n  };\n\n  return (\n    <SemiUIModal\n      style={isRtl(i18n.language) ? { direction: \"rtl\" } : {}}\n      title={getModalTitle(modal)}\n      visible={modal !== MODAL.NONE}\n      onOk={getModalOnOk}\n      afterClose={() => {\n        setExportData(() => ({\n          data: \"\",\n          extension: \"\",\n          filename: `${title}_${new Date().toISOString()}`,\n        }));\n        setError({\n          type: STATUS.NONE,\n          message: \"\",\n        });\n        setImportData(null);\n        setImportSource({\n          src: \"\",\n          overwrite: false,\n        });\n      }}\n      onCancel={() => {\n        if (modal === MODAL.RENAME) setUncontrolledTitle(title);\n        if (modal === MODAL.LANGUAGE) setUncontrolledLanguage(i18n.language);\n        if (modal === MODAL.TABLE_WIDTH) setTempTableWidth(settings.tableWidth);\n        setModal(MODAL.NONE);\n      }}\n      centered\n      closeOnEsc={true}\n      okText={getOkText(modal)}\n      okButtonProps={{\n        disabled:\n          (error && error?.type === STATUS.ERROR) ||\n          (modal === MODAL.IMPORT &&\n            (error.type === STATUS.ERROR || !importData)) ||\n          (modal === MODAL.RENAME && title === \"\") ||\n          ((modal === MODAL.IMG || modal === MODAL.CODE) && !exportData.data) ||\n          (modal === MODAL.SAVEAS && saveAsTitle === \"\") ||\n          (modal === MODAL.IMPORT_SRC && importSource.src === \"\"),\n        hidden: modal === MODAL.SHARE,\n      }}\n      hasCancel={modal !== MODAL.SHARE}\n      cancelText={t(\"cancel\")}\n      width={getModalWidth(modal)}\n      bodyStyle={{\n        maxHeight: window.innerHeight - 280,\n        overflow:\n          modal === MODAL.CODE || modal === MODAL.IMG ? \"hidden\" : \"auto\",\n        direction: \"ltr\",\n      }}\n    >\n      {getModalBody()}\n    </SemiUIModal>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/Modal/New.jsx",
    "content": "import { db } from \"../../../data/db\";\nimport { useSettings } from \"../../../hooks\";\nimport { useLiveQuery } from \"dexie-react-hooks\";\nimport Thumbnail from \"../../Thumbnail\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function New({ selectedTemplateId, setSelectedTemplateId }) {\n  const { settings } = useSettings();\n  const { t } = useTranslation();\n  const templates = useLiveQuery(() => db.templates.toArray());\n\n  return (\n    <div className=\"grid grid-cols-3 gap-2 overflow-auto px-1\">\n      <div onClick={() => setSelectedTemplateId(\"blank\")}>\n        <div\n          className={`rounded-md h-[180px] border-2 hover:border-dashed ${\n            selectedTemplateId === \"blank\" ? \"border-blue-400\" : \"border-zinc-400\"\n          }`}\n        >\n          <Thumbnail i=\"blank\" diagram={{}} zoom={0.24} theme={settings.mode} />\n        </div>\n        <div className=\"text-center mt-1\">{t(\"blank\")}</div>\n      </div>\n      {templates?.map((temp) => (\n        <div\n          key={temp.templateId}\n          onClick={() => setSelectedTemplateId(temp.templateId)}\n        >\n          <div\n            className={`rounded-md h-[180px] border-2 hover:border-dashed ${\n              selectedTemplateId === temp.templateId\n                ? \"border-blue-400\"\n                : \"border-zinc-400\"\n            }`}\n          >\n            <Thumbnail\n              i={temp.templateId}\n              diagram={temp}\n              zoom={0.24}\n              theme={settings.mode}\n            />\n          </div>\n          <div className=\"text-center mt-1\">{temp.title}</div>\n        </div>\n      ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/Modal/Open.jsx",
    "content": "import { db } from \"../../../data/db\";\nimport { Banner } from \"@douyinfe/semi-ui\";\nimport { useLiveQuery } from \"dexie-react-hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport { databases } from \"../../../data/databases\";\n\nexport default function Open({ selectedDiagramId, setSelectedDiagramId }) {\n  const diagrams = useLiveQuery(() => db.diagrams.toArray());\n  const { t } = useTranslation();\n\n  const getDiagramSize = (d) => {\n    const size = JSON.stringify(d).length;\n    let sizeStr;\n    if (size >= 1024 && size < 1024 * 1024)\n      sizeStr = (size / 1024).toFixed(1) + \"KB\";\n    else if (size >= 1024 * 1024)\n      sizeStr = (size / (1024 * 1024)).toFixed(1) + \"MB\";\n    else sizeStr = size + \"B\";\n\n    return sizeStr;\n  };\n\n  return (\n    <div>\n      {diagrams?.length === 0 ? (\n        <Banner\n          fullMode={false}\n          type=\"info\"\n          bordered\n          icon={null}\n          closeIcon={null}\n          description={<div>{t(\"no_saved_diagrams\")}</div>}\n        />\n      ) : (\n        <div className=\"max-h-[360px]\">\n          <table className=\"w-full text-left border-separate border-spacing-x-0\">\n            <thead>\n              <tr>\n                <th>{t(\"name\")}</th>\n                <th>{t(\"last_modified\")}</th>\n                <th>{t(\"size\")}</th>\n                <th>{t(\"type\")}</th>\n              </tr>\n            </thead>\n            <tbody>\n              {diagrams?.map((d) => {\n                return (\n                  <tr\n                    key={d.diagramId}\n                    className={`${\n                      selectedDiagramId === d.diagramId ? \"bg-blue-300/30\" : \"hover-1\"\n                    }`}\n                    onClick={() => {\n                      setSelectedDiagramId(d.diagramId);\n                    }}\n                  >\n                    <td className=\"py-1\">\n                      <i className=\"bi bi-file-earmark-text text-[16px] me-1 opacity-60\" />\n                      {d.name}\n                    </td>\n                    <td className=\"py-1\">\n                      {d.lastModified.toLocaleDateString() +\n                        \" \" +\n                        d.lastModified.toLocaleTimeString()}\n                    </td>\n                    <td className=\"py-1\">{getDiagramSize(d)}</td>\n                    <td className=\"py-1\">\n                      {databases[d.database].name ?? \"Generic\"}\n                    </td>\n                  </tr>\n                );\n              })}\n            </tbody>\n          </table>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/Modal/Rename.jsx",
    "content": "import { Input } from \"@douyinfe/semi-ui\";\nimport { useTranslation } from \"react-i18next\";\nimport { useLayout } from \"../../../hooks\";\n\nexport default function Rename({ title, setTitle }) {\n  const { t } = useTranslation();\n  const { layout } = useLayout();\n\n  return (\n    <Input\n      placeholder={t(\"name\")}\n      defaultValue={title}\n      onChange={(v) => setTitle(v)}\n      readonly={layout.readOnly}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/Modal/SetTableWidth.jsx",
    "content": "import { InputNumber } from \"@douyinfe/semi-ui\";\nimport { useLayout } from \"../../../hooks\";\n\nexport default function SetTableWidth({ tempWidth, setTempWidth }) {\n  const { layout } = useLayout();\n\n  return (\n    <InputNumber\n      className=\"w-full\"\n      value={tempWidth}\n      readonly={layout.readOnly}\n      onChange={(c) => {\n        if (c < 180) return;\n        setTempWidth(c);\n      }}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/Modal/Share.jsx",
    "content": "import { Banner, Button, Input, Spin, Toast } from \"@douyinfe/semi-ui\";\nimport { useCallback, useContext, useEffect, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { IdContext } from \"../../Workspace\";\nimport { IconLink } from \"@douyinfe/semi-icons\";\nimport {\n  useAreas,\n  useDiagram,\n  useEnums,\n  useNotes,\n  useTransform,\n  useTypes,\n} from \"../../../hooks\";\nimport { databases } from \"../../../data/databases\";\nimport { MODAL } from \"../../../data/constants\";\nimport { create, patch, SHARE_FILENAME } from \"../../../api/gists\";\n\nexport default function Share({ title, setModal }) {\n  const { t } = useTranslation();\n  const { gistId, setGistId } = useContext(IdContext);\n  const [loading, setLoading] = useState(true);\n  const { tables, relationships, database } = useDiagram();\n  const { notes } = useNotes();\n  const { areas } = useAreas();\n  const { types } = useTypes();\n  const { enums } = useEnums();\n  const { transform } = useTransform();\n  const [error, setError] = useState(null);\n  const url = window.location.origin + \"/editor?shareId=\" + gistId;\n\n  const diagramToString = useCallback(() => {\n    return JSON.stringify({\n      title,\n      tables: tables,\n      relationships: relationships,\n      notes: notes,\n      subjectAreas: areas,\n      database: database,\n      ...(databases[database].hasTypes && { types: types }),\n      ...(databases[database].hasEnums && { enums: enums }),\n      transform: transform,\n    });\n  }, [\n    areas,\n    notes,\n    tables,\n    relationships,\n    database,\n    title,\n    enums,\n    types,\n    transform,\n  ]);\n\n  const unshare = useCallback(async () => {\n    try {\n      const deleted = await patch(gistId, SHARE_FILENAME, undefined);\n      if (deleted) {\n        setGistId(\"\");\n      }\n      setModal(MODAL.NONE);\n    } catch (e) {\n      console.error(e);\n      setError(e);\n    }\n  }, [gistId, setModal, setGistId]);\n\n  useEffect(() => {\n    const updateOrGenerateLink = async () => {\n      try {\n        setLoading(true);\n        if (!gistId || gistId === \"\") {\n          const id = await create(SHARE_FILENAME, diagramToString());\n          setGistId(id);\n        } else {\n          await patch(gistId, SHARE_FILENAME, diagramToString());\n        }\n      } catch (e) {\n        setError(e);\n      } finally {\n        setLoading(false);\n      }\n    };\n    updateOrGenerateLink();\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  const copyLink = () => {\n    navigator.clipboard\n      .writeText(url)\n      .then(() => {\n        Toast.success(t(\"copied_to_clipboard\"));\n      })\n      .catch(() => {\n        Toast.error(t(\"oops_smth_went_wrong\"));\n      });\n  };\n\n  if (loading)\n    return (\n      <div className=\"text-blue-500 text-center\">\n        <Spin size=\"middle\" />\n        <div>{t(\"loading\")}</div>\n      </div>\n    );\n\n  return (\n    <div>\n      {error && (\n        <Banner\n          description={t(\"oops_smth_went_wrong\")}\n          type=\"danger\"\n          closeIcon={null}\n          fullMode={false}\n        />\n      )}\n      {!error && (\n        <>\n          <div className=\"flex gap-3\">\n            <Input value={url} size=\"large\" readonly />\n          </div>\n          <div className=\"text-xs mt-2\">{t(\"share_info\")}</div>\n          <div className=\"flex gap-2 mt-3\">\n            <Button block onClick={unshare}>\n              {t(\"unshare\")}\n            </Button>\n            <Button block theme=\"solid\" icon={<IconLink />} onClick={copyLink}>\n              {t(\"copy_link\")}\n            </Button>\n          </div>\n        </>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/SideSheet/Migration.jsx",
    "content": "import { useCallback, useState } from \"react\";\nimport { Tabs, TabPane, Modal, Input, Tag, Spin } from \"@douyinfe/semi-ui\";\nimport { DiffEditor } from \"@monaco-editor/react\";\nimport { useEffect } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useSettings } from \"../../../hooks\";\nimport { compare, VERSION_FILENAME } from \"../../../api/gists\";\nimport { deepDiff } from \"../../../utils/diff\";\nimport { DateTime } from \"luxon\";\nimport CodeEditor from \"../../CodeEditor\";\nimport { generateMigrationSQL } from \"../../../utils/migrations/diffToSQL\";\n\nexport default function Migration({\n  gistId,\n  selectedVersion,\n  versionToCompareTo,\n  setSelectedVersion,\n}) {\n  const { t } = useTranslation();\n  const { settings } = useSettings();\n  const [loading, setLoading] = useState(false);\n  const [contentA, setContentA] = useState(\"\");\n  const [contentB, setContentB] = useState(\"\");\n  const [filename, setFilename] = useState(\n    `${DateTime.now().toFormat(\"yyyyMMddHHmmss\")}-migration`,\n  );\n  const [migrationSQL, setMigrationSQL] = useState({\n    up: \"\",\n    down: \"\",\n  });\n\n  const getDiff = useCallback(async () => {\n    try {\n      setLoading(true);\n      const diff = {};\n      const { data } = await compare(\n        gistId,\n        VERSION_FILENAME,\n        selectedVersion,\n        versionToCompareTo,\n      );\n      setContentA(JSON.stringify(JSON.parse(data.contentA), null, 2));\n      setContentB(\n        data.contentB ? JSON.stringify(JSON.parse(data.contentB), null, 2) : \"\",\n      );\n\n      const keysToIgnore = [\n        \"x\",\n        \"y\",\n        \"width\",\n        \"height\",\n        \"locked\",\n        \"color\",\n        \"title\",\n        \"transform\",\n        \"notes\",\n        \"subjectAreas\",\n        \"database\",\n      ];\n\n      deepDiff(\n        data.contentB ? JSON.parse(data.contentB) : {},\n        JSON.parse(data.contentA),\n        diff,\n        keysToIgnore,\n      );\n      const diagramA = data.contentA ? JSON.parse(data.contentA) : {};\n      const diagramB = data.contentB ? JSON.parse(data.contentB) : {};\n      const database = diagramA.database;\n      setMigrationSQL(\n        generateMigrationSQL(diff, database, { from: diagramB, to: diagramA }),\n      );\n    } catch (error) {\n      console.error(error);\n    } finally {\n      setLoading(false);\n    }\n  }, [gistId, selectedVersion, versionToCompareTo]);\n\n  useEffect(() => {\n    if (versionToCompareTo === \"\") {\n      setLoading(true);\n      return;\n    }\n    if (!gistId || !selectedVersion) return;\n    getDiff();\n  }, [getDiff, gistId, selectedVersion, versionToCompareTo]);\n\n  if (!selectedVersion) return null;\n\n  return (\n    <Modal\n      centered\n      size=\"medium\"\n      title={\n        <div className=\"flex items-center gap-2\">\n          {t(\"migrations\")} <Tag color=\"blue\">Beta</Tag>\n        </div>\n      }\n      visible={!!selectedVersion}\n      onCancel={() => setSelectedVersion(null)}\n    >\n      <Tabs lazyRender keepDOM={false} className=\"h-[26rem] -mt-3\">\n        <TabPane tab={t(\"scripts\")} itemKey=\"1\">\n          {loading && (\n            <div className=\"text-blue-500 flex flex-col gap-2 justify-center items-center h-[24rem]\">\n              <Spin size=\"middle\" />\n              <div>{t(\"loading\")}</div>\n            </div>\n          )}\n\n          {!loading && migrationSQL?.up && (\n            <>\n              <CodeEditor\n                language=\"sql\"\n                height=\"9rem\"\n                filename={`${filename}.up.sql`}\n                value={migrationSQL.up}\n                options={{ readOnly: true }}\n              />\n              <CodeEditor\n                language=\"sql\"\n                height=\"9rem\"\n                filename={`${filename}.down.sql`}\n                value={migrationSQL.down}\n                className=\"mt-2\"\n                options={{ readOnly: true }}\n              />\n            </>\n          )}\n\n          {!loading && !migrationSQL?.up && (\n            <div className=\"text-center opacity-60 mt-44\">\n              {t(\"no_migration_needed\")}\n            </div>\n          )}\n        </TabPane>\n\n        <TabPane tab={t(\"json_diff\")} itemKey=\"2\">\n          {!loading && (\n            <DiffEditor\n              original={contentB}\n              modified={contentA}\n              options={{ readOnly: true }}\n              height=\"22rem\"\n              theme={settings.mode === \"light\" ? \"vs\" : \"vs-dark\"}\n              language=\"json\"\n            />\n          )}\n          {loading && (\n            <div className=\"text-blue-500 flex flex-col gap-2 justify-center items-center h-[24rem]\">\n              <Spin size=\"middle\" />\n              <div>{t(\"loading\")}</div>\n            </div>\n          )}\n        </TabPane>\n      </Tabs>\n      <div className=\"text-sm font-semibold mt-2\">{t(\"filename\")}:</div>\n      <Input\n        value={filename}\n        placeholder={t(\"filename\")}\n        suffix={<div className=\"p-2\">.zip</div>}\n        onChange={(value) => setFilename(value)}\n        field=\"filename\"\n      />\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/SideSheet/Sidesheet.jsx",
    "content": "import { SideSheet as SemiUISideSheet } from \"@douyinfe/semi-ui\";\nimport { SIDESHEET } from \"../../../data/constants\";\nimport Timeline from \"./Timeline\";\nimport Versions from \"./Versions\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function Sidesheet({ type, title, setTitle, onClose }) {\n  const { t } = useTranslation();\n\n  function getTitle(type) {\n    switch (type) {\n      case SIDESHEET.TIMELINE:\n        return t(\"timeline\");\n      case SIDESHEET.VERSIONS:\n        return t(\"versions\");\n      default:\n        break;\n    }\n  }\n\n  function getContent(type) {\n    switch (type) {\n      case SIDESHEET.TIMELINE:\n        return <Timeline />;\n      case SIDESHEET.VERSIONS:\n        return (\n          <Versions\n            open={type !== SIDESHEET.NONE}\n            title={title}\n            setTitle={setTitle}\n          />\n        );\n      default:\n        break;\n    }\n  }\n\n  return (\n    <SemiUISideSheet\n      visible={type !== SIDESHEET.NONE}\n      onCancel={onClose}\n      width={420}\n      title={<div className=\"text-lg\">{getTitle(type)}</div>}\n      style={{ paddingBottom: \"16px\" }}\n      bodyStyle={{ padding: \"0px\" }}\n    >\n      <div className=\"sidesheet-theme\">{getContent(type)}</div>\n    </SemiUISideSheet>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorHeader/SideSheet/Timeline.jsx",
    "content": "import { useTranslation } from \"react-i18next\";\nimport { useUndoRedo } from \"../../../hooks\";\nimport { List } from \"@douyinfe/semi-ui\";\n\nexport default function Timeline() {\n  const { undoStack } = useUndoRedo();\n  const { t } = useTranslation();\n\n  if (undoStack.length > 0) {\n    return (\n      <List>\n        {[...undoStack].reverse().map((e, i) => (\n          <List.Item\n            key={i}\n            style={{ padding: \"4px 18px 4px 18px\" }}\n            className=\"hover-1\"\n          >\n            <div className=\"flex items-center py-1 w-full\">\n              <i className=\"block fa-regular fa-circle fa-xs\" />\n              <div className=\"ms-2\">{e.message}</div>\n            </div>\n          </List.Item>\n        ))}\n      </List>\n    );\n  } else {\n    return <div className=\"m-5\">{t(\"no_activity\")}</div>;\n  }\n}\n"
  },
  {
    "path": "src/components/EditorHeader/SideSheet/Versions.jsx",
    "content": "import { useCallback, useContext, useEffect, useState, useMemo } from \"react\";\nimport { IdContext } from \"../../Workspace\";\nimport { useTranslation } from \"react-i18next\";\nimport { Button, Spin, Steps, Tag, Toast, Tooltip } from \"@douyinfe/semi-ui\";\nimport { IconPlus } from \"@douyinfe/semi-icons\";\nimport {\n  create,\n  getCommitsWithFile,\n  getVersion,\n  patch,\n  get,\n  VERSION_FILENAME,\n} from \"../../../api/gists\";\nimport _ from \"lodash\";\nimport { DateTime } from \"luxon\";\nimport {\n  useAreas,\n  useDiagram,\n  useEnums,\n  useLayout,\n  useNotes,\n  useTransform,\n  useTypes,\n} from \"../../../hooks\";\nimport { databases } from \"../../../data/databases\";\nimport { loadCache, saveCache } from \"../../../utils/cache\";\nimport Migration from \"./Migration\";\nimport { DB } from \"../../../data/constants\";\n\nconst LIMIT = 10;\n\nexport default function Versions({ open, title, setTitle }) {\n  const { gistId, setGistId, version, setVersion } = useContext(IdContext);\n  const { areas, setAreas } = useAreas();\n  const { setLayout } = useLayout();\n  const { database, tables, relationships, setTables, setRelationships } =\n    useDiagram();\n  const { notes, setNotes } = useNotes();\n  const { types, setTypes } = useTypes();\n  const { enums, setEnums } = useEnums();\n  const { transform } = useTransform();\n  const { t, i18n } = useTranslation();\n  const [isLoading, setIsLoading] = useState(false);\n  const [versions, setVersions] = useState([]);\n  const [hasMore, setHasMore] = useState(false);\n  const [cursor, setCursor] = useState(null);\n  const [isRecording, setIsRecording] = useState(false);\n  const [loadingVersion, setLoadingVersion] = useState(null);\n  const [selectedVersion, setSelectedVersion] = useState(null);\n  const [versionToCompareTo, setVersionToCompareTo] = useState(null);\n\n  const cacheRef = useMemo(() => loadCache(), []);\n\n  const diagramToString = useCallback(() => {\n    return JSON.stringify({\n      title,\n      tables,\n      relationships: relationships,\n      notes: notes,\n      subjectAreas: areas,\n      database: database,\n      ...(databases[database].hasTypes && { types: types }),\n      ...(databases[database].hasEnums && { enums: enums }),\n      transform: transform,\n    });\n  }, [\n    areas,\n    notes,\n    tables,\n    relationships,\n    database,\n    title,\n    enums,\n    types,\n    transform,\n  ]);\n\n  const currentStep = useMemo(() => {\n    if (!version) return 0;\n    return versions.findIndex((v) => v.version === version);\n  }, [version, versions]);\n\n  const loadVersion = useCallback(\n    async (sha) => {\n      try {\n        setLoadingVersion(sha);\n        const version = await getVersion(gistId, sha);\n        setVersion(sha);\n        setLayout((prev) => ({ ...prev, readOnly: true }));\n\n        if (!version.data.files[VERSION_FILENAME]) {\n          return;\n        }\n\n        const content = version.data.files[VERSION_FILENAME].content;\n        const parsedDiagram = JSON.parse(content);\n\n        setTables(parsedDiagram.tables);\n        setRelationships(parsedDiagram.relationships);\n        setAreas(parsedDiagram.subjectAreas);\n        setNotes(parsedDiagram.notes);\n        setTitle(parsedDiagram.title);\n\n        if (databases[database].hasTypes) {\n          setTypes(parsedDiagram.types);\n        }\n\n        if (databases[database].hasEnums) {\n          setEnums(parsedDiagram.enums);\n        }\n      } catch (e) {\n        Toast.error(t(\"failed_to_load_diagram\"));\n      } finally {\n        setLoadingVersion(null);\n      }\n    },\n    [\n      t,\n      gistId,\n      setTables,\n      setRelationships,\n      setAreas,\n      setVersion,\n      setLayout,\n      database,\n      setNotes,\n      setTypes,\n      setEnums,\n      setTitle,\n    ],\n  );\n\n  const getRevisions = useCallback(\n    async (cursorParam) => {\n      try {\n        if (!gistId) return;\n\n        setIsLoading(true);\n\n        const cached = cacheRef[gistId];\n        if (cached && !cursorParam) {\n          setVersions(cached.versions);\n          setCursor(cached.cursor);\n          setHasMore(cached.hasMore);\n          setIsLoading(false);\n          return;\n        }\n\n        const res = await getCommitsWithFile(\n          gistId,\n          VERSION_FILENAME,\n          LIMIT,\n          cursorParam,\n        );\n\n        const newVersions = cursorParam ? [...versions, ...res.data] : res.data;\n\n        setVersions(newVersions);\n        setHasMore(res.pagination.hasMore);\n        setCursor(res.pagination.cursor);\n\n        cacheRef[gistId] = {\n          versions: newVersions,\n          cursor: res.pagination.cursor,\n          hasMore: res.pagination.hasMore,\n        };\n        saveCache(cacheRef);\n      } catch (e) {\n        Toast.error(t(\"oops_smth_went_wrong\"));\n      } finally {\n        setIsLoading(false);\n      }\n    },\n    [gistId, versions, t, cacheRef],\n  );\n\n  const hasDiagramChanged = async () => {\n    if (!gistId) return true;\n\n    const previousVersion = await get(gistId);\n\n    if (!previousVersion.data.files[VERSION_FILENAME]) {\n      return true;\n    }\n\n    const previousDiagram = JSON.parse(\n      previousVersion.data.files[VERSION_FILENAME]?.content,\n    );\n    const currentDiagram = {\n      title,\n      tables,\n      relationships: relationships,\n      notes: notes,\n      subjectAreas: areas,\n      database: database,\n      ...(databases[database].hasTypes && { types: types }),\n      ...(databases[database].hasEnums && { enums: enums }),\n      transform: transform,\n    };\n\n    return !_.isEqual(previousDiagram, currentDiagram);\n  };\n\n  const recordVersion = async () => {\n    try {\n      setIsRecording(true);\n      const hasChanges = await hasDiagramChanged();\n      if (!hasChanges) {\n        Toast.info(t(\"no_changes_to_record\"));\n        return;\n      }\n      if (gistId) {\n        await patch(gistId, VERSION_FILENAME, diagramToString());\n      } else {\n        const id = await create(VERSION_FILENAME, diagramToString());\n        setGistId(id);\n      }\n\n      delete cacheRef[gistId];\n      saveCache(cacheRef);\n\n      await getRevisions();\n    } catch (e) {\n      Toast.error(t(\"failed_to_record_version\"));\n    } finally {\n      setIsRecording(false);\n    }\n  };\n\n  const getVersionToCompareTo = useCallback(async () => {\n    if (!selectedVersion) return null;\n\n    const currentIndex = versions.findIndex(\n      (v) => v.version === selectedVersion,\n    );\n\n    if (currentIndex === -1) return null;\n\n    if (currentIndex === versions.length - 1 && hasMore) {\n      const res = await getCommitsWithFile(gistId, VERSION_FILENAME, 1, cursor);\n      const version = res.data.length ? res.data[0].version : \"null\";\n\n      if (version === selectedVersion) return null;\n\n      return version;\n    } else {\n      return versions[currentIndex + 1]?.version || \"null\";\n    }\n  }, [selectedVersion, versions, gistId, cursor, hasMore]);\n\n  useEffect(() => {\n    const getVersionToCompare = async () => {\n      const versionToCompare = await getVersionToCompareTo();\n      setVersionToCompareTo(versionToCompare);\n    };\n    getVersionToCompare();\n  }, [selectedVersion, getVersionToCompareTo]);\n\n  useEffect(() => {\n    if (gistId && open) {\n      getRevisions();\n    }\n  }, [gistId, open, getRevisions]);\n\n  return (\n    <div className=\"mx-5 relative h-full\">\n      <div className=\"sticky top-0 z-10 sidesheet-theme pb-2\">\n        <Button\n          block\n          icon={isRecording ? <Spin /> : <IconPlus />}\n          disabled={isLoading || isRecording}\n          onClick={recordVersion}\n        >\n          {t(\"record_version\")}\n        </Button>\n      </div>\n\n      {(!gistId || !versions.length) && !isLoading && (\n        <div className=\"my-3\">{t(\"no_saved_versions\")}</div>\n      )}\n      {gistId && (\n        <div className=\"my-2 overflow-y-auto\">\n          <Steps direction=\"vertical\" type=\"basic\" current={currentStep}>\n            {versions.map((r) => (\n              <Steps.Step\n                key={r.version}\n                onClick={() => loadVersion(r.version)}\n                className=\"group hover-1 first:!pt-2\"\n                title={\n                  <div className=\"flex justify-between items-center w-full\">\n                    <Tag>{r.version.substring(0, 7)}</Tag>\n                    {database === DB.GENERIC ? (\n                      <Tooltip content={t(\"migration_not_supported_generic\")}>\n                        <Button\n                          size=\"small\"\n                          theme=\"borderless\"\n                          className=\"!text-xs\"\n                          onClick={(e) => {\n                            e.stopPropagation();\n                            setSelectedVersion(r.version);\n                          }}\n                          disabled={database === DB.GENERIC}\n                        >\n                          {t(\"generate_migration\")}\n                        </Button>\n                      </Tooltip>\n                    ) : (\n                      <Button\n                        size=\"small\"\n                        theme=\"borderless\"\n                        className=\"!text-xs\"\n                        onClick={(e) => {\n                          e.stopPropagation();\n                          setSelectedVersion(r.version);\n                        }}\n                        disabled={database === DB.GENERIC}\n                      >\n                        {t(\"generate_migration\")}\n                      </Button>\n                    )}\n                  </div>\n                }\n                description={`${t(\"commited_at\")} ${DateTime.fromISO(\n                  r.committed_at,\n                )\n                  .setLocale(i18n.language)\n                  .toLocaleString(DateTime.DATETIME_MED)}`}\n                icon={\n                  r.version === loadingVersion ? (\n                    <Spin size=\"small\" />\n                  ) : (\n                    <i className=\"text-sm fa-solid fa-asterisk ms-1\" />\n                  )\n                }\n              />\n            ))}\n          </Steps>\n        </div>\n      )}\n      {isLoading && !isRecording && (\n        <div className=\"text-blue-500 text-center my-3\">\n          <Spin size=\"middle\" />\n          <div>{t(\"loading\")}</div>\n        </div>\n      )}\n      {hasMore && !isLoading && (\n        <div className=\"text-center\">\n          <Button onClick={() => getRevisions(cursor)}>{t(\"load_more\")}</Button>\n        </div>\n      )}\n\n      <Migration\n        gistId={gistId}\n        selectedVersion={selectedVersion}\n        versionToCompareTo={versionToCompareTo || \"\"}\n        setSelectedVersion={setSelectedVersion}\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/AreasTab/AreaDetails.jsx",
    "content": "import { useState, useRef } from \"react\";\nimport { Button, Input } from \"@douyinfe/semi-ui\";\nimport ColorPicker from \"../ColorPicker\";\nimport { IconDeleteStroked } from \"@douyinfe/semi-icons\";\nimport { useAreas, useLayout, useUndoRedo } from \"../../../hooks\";\nimport { Action, ObjectType } from \"../../../data/constants\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function AreaInfo({ data, i }) {\n  const { t } = useTranslation();\n  const { layout } = useLayout();\n  const { deleteArea, updateArea } = useAreas();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const [editField, setEditField] = useState({});\n  const initialColorRef = useRef(data.color);\n\n  const handleColorPick = (color) => {\n    setUndoStack((prev) => {\n      let undoColor = initialColorRef.current;\n      const lastColorChange = prev.findLast(\n        (e) =>\n          e.element === ObjectType.AREA &&\n          e.aid === data.id &&\n          e.action === Action.EDIT &&\n          e.redo?.color,\n      );\n      if (lastColorChange) {\n        undoColor = lastColorChange.redo.color;\n      }\n\n      if (color === undoColor) return prev;\n\n      const newStack = [\n        ...prev,\n        {\n          action: Action.EDIT,\n          element: ObjectType.AREA,\n          aid: i,\n          undo: { color: undoColor },\n          redo: { color: color },\n          message: t(\"edit_area\", {\n            areaName: data.name,\n            extra: \"[color]\",\n          }),\n        },\n      ];\n      return newStack;\n    });\n    setRedoStack([]);\n  };\n\n  return (\n    <div id={`scroll_area_${data.id}`} className=\"my-3 flex gap-2 items-center\">\n      <Input\n        value={data.name}\n        placeholder={t(\"name\")}\n        readonly={layout.readOnly}\n        onChange={(value) => updateArea(data.id, { name: value })}\n        onFocus={(e) => setEditField({ name: e.target.value })}\n        onBlur={(e) => {\n          if (e.target.value === editField.name) return;\n          setUndoStack((prev) => [\n            ...prev,\n            {\n              action: Action.EDIT,\n              element: ObjectType.AREA,\n              aid: i,\n              undo: editField,\n              redo: { name: e.target.value },\n              message: t(\"edit_area\", {\n                areaName: e.target.value,\n                extra: \"[name]\",\n              }),\n            },\n          ]);\n          setRedoStack([]);\n        }}\n      />\n      <ColorPicker\n        usePopover={true}\n        value={data.color}\n        readOnly={layout.readOnly}\n        onChange={(color) => updateArea(i, { color })}\n        onColorPick={(color) => handleColorPick(color)}\n      />\n      <Button\n        type=\"danger\"\n        disabled={layout.readOnly}\n        icon={<IconDeleteStroked />}\n        onClick={() => deleteArea(i, true)}\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/AreasTab/AreasTab.jsx",
    "content": "import { Button } from \"@douyinfe/semi-ui\";\nimport { IconPlus } from \"@douyinfe/semi-icons\";\nimport Empty from \"../Empty\";\nimport { useAreas, useLayout } from \"../../../hooks\";\nimport SearchBar from \"./SearchBar\";\nimport AreaInfo from \"./AreaDetails\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function AreasTab() {\n  const { areas, addArea } = useAreas();\n  const { layout } = useLayout();\n  const { t } = useTranslation();\n\n  return (\n    <div>\n      <div className=\"flex gap-2\">\n        <SearchBar />\n        <div>\n          <Button\n            icon={<IconPlus />}\n            block\n            onClick={() => addArea()}\n            disabled={layout.readOnly}\n          >\n            {t(\"add_area\")}\n          </Button>\n        </div>\n      </div>\n      {areas.length <= 0 ? (\n        <Empty\n          title={t(\"no_subject_areas\")}\n          text={t(\"no_subject_areas_text\")}\n        />\n      ) : (\n        <div className=\"p-2\">\n          {areas.map((a, i) => (\n            <AreaInfo data={a} key={\"area_\" + i} i={i} />\n          ))}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/AreasTab/SearchBar.jsx",
    "content": "import { useState } from \"react\";\nimport { useAreas } from \"../../../hooks\";\nimport { AutoComplete } from \"@douyinfe/semi-ui\";\nimport { IconSearch } from \"@douyinfe/semi-icons\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function SearchBar() {\n  const { areas } = useAreas();\n  const [searchText, setSearchText] = useState(\"\");\n  const { t } = useTranslation();\n\n  const [filteredResult, setFilteredResult] = useState(\n    areas.map((t) => t.name),\n  );\n\n  const handleStringSearch = (value) => {\n    setFilteredResult(\n      areas.map((t) => t.name).filter((i) => i.includes(value)),\n    );\n  };\n\n  return (\n    <AutoComplete\n      data={filteredResult}\n      value={searchText}\n      showClear\n      prefix={<IconSearch />}\n      placeholder={t(\"search\")}\n      emptyContent={<div className=\"p-3 popover-theme\">{t(\"not_found\")}</div>}\n      onSearch={(v) => handleStringSearch(v)}\n      onChange={(v) => setSearchText(v)}\n      onSelect={(v) => {\n        const { id } = areas.find((t) => t.name === v);\n        document\n          .getElementById(`scroll_area_${id}`)\n          .scrollIntoView({ behavior: \"smooth\" });\n      }}\n      className=\"w-full\"\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/ColorPicker.jsx",
    "content": "import { ColorPicker as SemiColorPicker } from \"@douyinfe/semi-ui\";\nimport { useState } from \"react\";\n\nexport default function ColorPicker({\n  value,\n  readOnly,\n  children,\n  onChange,\n  onColorPick,\n  ...props\n}) {\n  const [pickedColor, setPickedColor] = useState(null);\n\n  const handleColorPick = () => {\n    if (pickedColor) onColorPick(pickedColor);\n    setPickedColor(null);\n  };\n\n  return (\n    <div\n      onPointerUp={handleColorPick}\n      onBlur={handleColorPick}\n      onMouseLeave={handleColorPick}\n    >\n      <SemiColorPicker\n        {...props}\n        value={SemiColorPicker.colorStringToValue(value)}\n        onChange={({ hex: color }) => {\n          if (readOnly) return;\n          setPickedColor(color);\n          onChange(color);\n        }}\n      >\n        {children || (\n          <div\n            className=\"h-8 w-8 rounded-md\"\n            style={{ backgroundColor: value }}\n          />\n        )}\n      </SemiColorPicker>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/DBMLEditor.jsx",
    "content": "import { useEffect, useState } from \"react\";\nimport { useDiagram, useEnums, useLayout } from \"../../hooks\";\nimport { toDBML } from \"../../utils/exportAs/dbml\";\nimport { Button, Tooltip } from \"@douyinfe/semi-ui\";\nimport { IconTemplate } from \"@douyinfe/semi-icons\";\nimport { useTranslation } from \"react-i18next\";\nimport CodeEditor from \"../CodeEditor\";\n\nexport default function DBMLEditor() {\n  const { tables: currentTables, relationships } = useDiagram();\n  const diagram = useDiagram();\n  const { enums } = useEnums();\n  const [value, setValue] = useState(() => toDBML({ ...diagram, enums }));\n  const { setLayout } = useLayout();\n  const { t } = useTranslation();\n\n  const toggleDBMLEditor = () => {\n    setLayout((prev) => ({ ...prev, dbmlEditor: !prev.dbmlEditor }));\n  };\n\n  useEffect(() => {\n    setValue(toDBML({ tables: currentTables, enums, relationships }));\n  }, [currentTables, enums, relationships]);\n\n  return (\n    <CodeEditor\n      showCopyButton\n      value={value}\n      language=\"dbml\"\n      onChange={setValue}\n      height=\"100%\"\n      options={{\n        readOnly: true,\n        minimap: { enabled: false },\n      }}\n      extraControls={\n        <Tooltip content={t(\"tab_view\")}>\n          <Button icon={<IconTemplate />} onClick={toggleDBMLEditor} />\n        </Tooltip>\n      }\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/Empty.jsx",
    "content": "import {\n  IllustrationNoContent,\n  IllustrationNoContentDark,\n} from \"@douyinfe/semi-illustrations\";\nimport { Empty as SemiUIEmpty } from \"@douyinfe/semi-ui\";\n\nexport default function Empty({ title, text }) {\n  return (\n    <div className=\"select-none mt-2\">\n      <SemiUIEmpty\n        image={<IllustrationNoContent style={{ width: 154, height: 154 }} />}\n        darkModeImage={\n          <IllustrationNoContentDark style={{ width: 154, height: 154 }} />\n        }\n        title={title}\n        description={text}\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/EnumsTab/EnumDetails.jsx",
    "content": "import { useState } from \"react\";\nimport { Button, Input, TagInput } from \"@douyinfe/semi-ui\";\nimport { IconDeleteStroked } from \"@douyinfe/semi-icons\";\nimport { useDiagram, useEnums, useLayout, useUndoRedo } from \"../../../hooks\";\nimport { Action, ObjectType } from \"../../../data/constants\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function EnumDetails({ data }) {\n  const { t } = useTranslation();\n  const { layout } = useLayout();\n  const { deleteEnum, updateEnum } = useEnums();\n  const { tables, updateField } = useDiagram();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const [editField, setEditField] = useState({});\n\n  return (\n    <>\n      <div className=\"flex justify-center items-center gap-2\">\n        <div className=\"font-semibold\">{t(\"Name\")}: </div>\n        <Input\n          value={data.name}\n          readonly={layout.readOnly}\n          placeholder={t(\"name\")}\n          validateStatus={data.name.trim() === \"\" ? \"error\" : \"default\"}\n          onChange={(value) => {\n            updateEnum(data.id, { name: value });\n            tables.forEach((table) => {\n              table.fields.forEach((field) => {\n                if (field.type.toLowerCase() === data.name.toLowerCase()) {\n                  updateField(table.id, field.id, {\n                    type: value.toUpperCase(),\n                  });\n                }\n              });\n            });\n          }}\n          onFocus={(e) => setEditField({ name: e.target.value })}\n          onBlur={(e) => {\n            if (e.target.value === editField.name) return;\n\n            const updatedFields = tables.reduce((acc, table) => {\n              table.fields.forEach((field, i) => {\n                if (field.type.toLowerCase() === data.name.toLowerCase()) {\n                  acc.push({ tid: table.id, fid: i });\n                }\n              });\n              return acc;\n            }, []);\n\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.ENUM,\n                id: data.id,\n                undo: editField,\n                redo: { name: e.target.value },\n                updatedFields,\n                message: t(\"edit_enum\", {\n                  enumName: e.target.value,\n                  extra: \"[name]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n          }}\n        />\n      </div>\n      <TagInput\n        separator={[\",\", \", \", \" ,\"]}\n        value={data.values}\n        addOnBlur\n        className=\"my-2\"\n        placeholder={t(\"values\")}\n        validateStatus={data.values.length === 0 ? \"error\" : \"default\"}\n        onChange={(v) => {\n          if (layout.readOnly) return;\n          updateEnum(data.id, { values: v });\n        }}\n        onFocus={() => setEditField({ values: data.values })}\n        onBlur={() => {\n          if (JSON.stringify(editField.values) === JSON.stringify(data.values))\n            return;\n          setUndoStack((prev) => [\n            ...prev,\n            {\n              action: Action.EDIT,\n              element: ObjectType.ENUM,\n              id: data.id,\n              undo: editField,\n              redo: { values: data.values },\n              message: t(\"edit_enum\", {\n                enumName: data.name,\n                extra: \"[values]\",\n              }),\n            },\n          ]);\n          setRedoStack([]);\n        }}\n      />\n      <Button\n        block\n        type=\"danger\"\n        icon={<IconDeleteStroked />}\n        disabled={layout.readOnly}\n        onClick={() => deleteEnum(data.id, true)}\n      >\n        {t(\"delete\")}\n      </Button>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/EnumsTab/EnumsTab.jsx",
    "content": "import { Button, Collapse } from \"@douyinfe/semi-ui\";\nimport { useEnums, useLayout } from \"../../../hooks\";\nimport { IconPlus } from \"@douyinfe/semi-icons\";\nimport { useTranslation } from \"react-i18next\";\nimport SearchBar from \"./SearchBar\";\nimport EnumDetails from \"./EnumDetails\";\nimport Empty from \"../Empty\";\n\nexport default function EnumsTab() {\n  const { enums, addEnum } = useEnums();\n  const { layout } = useLayout();\n  const { t } = useTranslation();\n\n  return (\n    <div>\n      <div className=\"flex gap-2\">\n        <SearchBar />\n        <div>\n          <Button\n            block\n            icon={<IconPlus />}\n            onClick={() => addEnum()}\n            disabled={layout.readOnly}\n          >\n            {t(\"add_enum\")}\n          </Button>\n        </div>\n      </div>\n      {enums.length <= 0 ? (\n        <Empty title={t(\"no_enums\")} text={t(\"no_enums_text\")} />\n      ) : (\n        <Collapse accordion>\n          {enums.map((e) => (\n            <Collapse.Panel\n              key={`enum_${e.id}`}\n              id={`scroll_enum_${e.id}`}\n              header={\n                <div className=\"overflow-hidden text-ellipsis whitespace-nowrap\">\n                  {e.name}\n                </div>\n              }\n              itemKey={e.id}\n            >\n              <EnumDetails data={e} />\n            </Collapse.Panel>\n          ))}\n        </Collapse>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/EnumsTab/SearchBar.jsx",
    "content": "import { useState } from \"react\";\nimport { AutoComplete } from \"@douyinfe/semi-ui\";\nimport { IconSearch } from \"@douyinfe/semi-icons\";\nimport { useEnums } from \"../../../hooks\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function SearchBar() {\n  const { enums } = useEnums();\n  const [value, setValue] = useState(\"\");\n  const { t } = useTranslation();\n\n  const [filteredResult, setFilteredResult] = useState(\n    enums.map((e) => e.name),\n  );\n\n  const handleStringSearch = (value) => {\n    setFilteredResult(\n      enums.map((e) => e.name).filter((i) => i.includes(value)),\n    );\n  };\n\n  return (\n    <AutoComplete\n      data={filteredResult}\n      value={value}\n      showClear\n      prefix={<IconSearch />}\n      placeholder={t(\"search\")}\n      onSearch={(v) => handleStringSearch(v)}\n      emptyContent={<div className=\"p-3 popover-theme\">{t(\"not_found\")}</div>}\n      onChange={(v) => setValue(v)}\n      onSelect={(v) => {\n        const e = enums.find((t) => t.name === v);\n        document\n          .getElementById(`scroll_enum_${e.id}`)\n          .scrollIntoView({ behavior: \"smooth\" });\n      }}\n      className=\"w-full\"\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/Issues.jsx",
    "content": "import { useState, useEffect } from \"react\";\nimport { Collapse, Badge } from \"@douyinfe/semi-ui\";\nimport { arrayIsEqual } from \"../../utils/utils\";\nimport { getIssues } from \"../../utils/issues\";\nimport { useEnums, useSettings, useDiagram, useTypes } from \"../../hooks\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function Issues() {\n  const { types } = useTypes();\n  const { t } = useTranslation();\n  const { settings } = useSettings();\n  const { enums } = useEnums();\n  const { tables, relationships, database } = useDiagram();\n  const [issues, setIssues] = useState([]);\n\n  useEffect(() => {\n    const findIssues = async () => {\n      const newIssues = getIssues({\n        tables: tables,\n        relationships: relationships,\n        types: types,\n        database: database,\n        enums: enums,\n      });\n\n      if (!arrayIsEqual(newIssues, issues)) {\n        setIssues(newIssues);\n      }\n    };\n\n    findIssues();\n  }, [tables, relationships, issues, types, database, enums]);\n\n  return (\n    <Collapse lazyRender keepDOM={false} style={{ width: \"100%\" }}>\n      <Collapse.Panel\n        header={\n          <Badge\n            type={issues.length > 0 ? \"danger\" : \"primary\"}\n            count={settings.strictMode ? null : issues.length}\n            overflowCount={99}\n            className=\"mt-1\"\n          >\n            <div className=\"pe-3 select-none\">\n              <i className=\"fa-solid fa-triangle-exclamation me-2 text-yellow-500\" />\n              {t(\"issues\")}\n            </div>\n          </Badge>\n        }\n        itemKey=\"1\"\n      >\n        <div className=\"max-h-[160px] overflow-y-auto\">\n          {settings.strictMode ? (\n            <div className=\"mb-1\">{t(\"strict_mode_is_on_no_issues\")}</div>\n          ) : issues.length > 0 ? (\n            <>\n              {issues.map((e, i) => (\n                <div key={i} className=\"py-2\">\n                  {e}\n                </div>\n              ))}\n            </>\n          ) : (\n            <div>{t(\"no_issues\")}</div>\n          )}\n        </div>\n      </Collapse.Panel>\n    </Collapse>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/NotesTab/NoteInfo.jsx",
    "content": "import { useState, useRef } from \"react\";\nimport { Button, Collapse, TextArea, Input } from \"@douyinfe/semi-ui\";\nimport ColorPicker from \"../ColorPicker\";\nimport { IconDeleteStroked } from \"@douyinfe/semi-icons\";\nimport { Action, ObjectType } from \"../../../data/constants\";\nimport { useLayout, useNotes, useUndoRedo } from \"../../../hooks\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function NoteInfo({ data, nid }) {\n  const { layout } = useLayout();\n  const { updateNote, deleteNote } = useNotes();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const [editField, setEditField] = useState({});\n  const { t } = useTranslation();\n  const initialColorRef = useRef(data.color);\n\n  const handleColorPick = (color) => {\n    setUndoStack((prev) => {\n      let undoColor = initialColorRef.current;\n      const lastColorChange = prev.findLast(\n        (e) =>\n          e.element === ObjectType.NOTE &&\n          e.nid === data.id &&\n          e.action === Action.EDIT &&\n          e.redo?.color,\n      );\n      if (lastColorChange) {\n        undoColor = lastColorChange.redo.color;\n      }\n\n      if (color === undoColor) return prev;\n\n      const newStack = [\n        ...prev,\n        {\n          action: Action.EDIT,\n          element: ObjectType.NOTE,\n          nid: data.id,\n          undo: { color: undoColor },\n          redo: { color: color },\n          message: t(\"edit_note\", {\n            noteTitle: data.title,\n            extra: \"[color]\",\n          }),\n        },\n      ];\n      return newStack;\n    });\n    setRedoStack([]);\n  };\n\n  return (\n    <Collapse.Panel\n      header={\n        <div className=\"overflow-hidden text-ellipsis whitespace-nowrap\">\n          {data.title}\n        </div>\n      }\n      itemKey={`${data.id}`}\n      id={`scroll_note_${data.id}`}\n    >\n      <div className=\"flex items-center mb-2\">\n        <div className=\"font-semibold me-2 break-keep\">{t(\"title\")}:</div>\n        <Input\n          value={data.title}\n          readonly={layout.readOnly}\n          placeholder={t(\"title\")}\n          onChange={(value) => updateNote(data.id, { title: value })}\n          onFocus={(e) => setEditField({ title: e.target.value })}\n          onBlur={(e) => {\n            if (e.target.value === editField.title) return;\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.NOTE,\n                nid: data.id,\n                undo: editField,\n                redo: { title: e.target.value },\n                message: t(\"edit_note\", {\n                  noteTitle: e.target.value,\n                  extra: \"[title]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n          }}\n        />\n      </div>\n      <div className=\"flex justify-between align-top\">\n        <TextArea\n          placeholder={t(\"content\")}\n          value={data.content}\n          autosize\n          readonly={layout.readOnly}\n          onChange={(value) => {\n            const textarea = document.getElementById(`note_${data.id}`);\n            textarea.style.height = \"0\";\n            textarea.style.height = textarea.scrollHeight + \"px\";\n            const newHeight = textarea.scrollHeight + 16 + 20 + 4;\n            updateNote(data.id, { height: newHeight, content: value });\n          }}\n          onFocus={(e) =>\n            setEditField({ content: e.target.value, height: data.height })\n          }\n          onBlur={(e) => {\n            if (e.target.value === editField.content) return;\n            const textarea = document.getElementById(`note_${data.id}`);\n            textarea.style.height = \"0\";\n            textarea.style.height = textarea.scrollHeight + \"px\";\n            const newHeight = textarea.scrollHeight + 16 + 20 + 4;\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.NOTE,\n                nid: nid,\n                undo: editField,\n                redo: { content: e.target.value, height: newHeight },\n                message: t(\"edit_note\", {\n                  noteTitle: e.target.value,\n                  extra: \"[content]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n          }}\n          rows={3}\n        />\n        <div className=\"ms-2 flex flex-col gap-2\">\n          <ColorPicker\n            usePopover={true}\n            readOnly={layout.readOnly}\n            value={data.color}\n            onChange={(color) => updateNote(data.id, { color })}\n            onColorPick={(color) => handleColorPick(color)}\n          />\n          <Button\n            type=\"danger\"\n            disabled={layout.readOnly}\n            icon={<IconDeleteStroked />}\n            onClick={() => deleteNote(nid, true)}\n          />\n        </div>\n      </div>\n    </Collapse.Panel>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/NotesTab/NotesTab.jsx",
    "content": "import { Button, Collapse } from \"@douyinfe/semi-ui\";\nimport { IconPlus } from \"@douyinfe/semi-icons\";\nimport { useLayout, useNotes, useSelect } from \"../../../hooks\";\nimport Empty from \"../Empty\";\nimport SearchBar from \"./SearchBar\";\nimport NoteInfo from \"./NoteInfo\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function NotesTab() {\n  const { notes, addNote } = useNotes();\n  const { selectedElement, setSelectedElement } = useSelect();\n  const { t } = useTranslation();\n  const { layout } = useLayout();\n\n  return (\n    <>\n      <div className=\"flex gap-2\">\n        <SearchBar\n          setActiveKey={(activeKey) =>\n            setSelectedElement((prev) => ({\n              ...prev,\n              id: parseInt(activeKey),\n            }))\n          }\n        />\n        <div>\n          <Button\n            block\n            icon={<IconPlus />}\n            onClick={() => addNote()}\n            disabled={layout.readOnly}\n          >\n            {t(\"add_note\")}\n          </Button>\n        </div>\n      </div>\n      {notes.length <= 0 ? (\n        <Empty title={t(\"no_notes\")} text={t(\"no_notes_text\")} />\n      ) : (\n        <Collapse\n          activeKey={selectedElement.open ? `${selectedElement.id}` : \"\"}\n          keepDOM={false}\n          lazyRender\n          onChange={(activeKey) => {\n            setSelectedElement((prev) => ({\n              ...prev,\n              id: parseInt(activeKey),\n              open: true,\n            }));\n          }}\n          accordion\n        >\n          {notes.map((n, i) => (\n            <NoteInfo data={n} key={i} nid={i} />\n          ))}\n        </Collapse>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/NotesTab/SearchBar.jsx",
    "content": "import { useState } from \"react\";\nimport { AutoComplete } from \"@douyinfe/semi-ui\";\nimport { IconSearch } from \"@douyinfe/semi-icons\";\nimport { useNotes } from \"../../../hooks\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function SearchBar({ setActiveKey }) {\n  const { notes } = useNotes();\n  const [searchText, setSearchText] = useState(\"\");\n  const { t } = useTranslation();\n\n  const [filteredResult, setFilteredResult] = useState(\n    notes.map((t) => t.title),\n  );\n\n  const handleStringSearch = (value) => {\n    setFilteredResult(\n      notes.map((t) => t.title).filter((i) => i.includes(value)),\n    );\n  };\n\n  return (\n    <AutoComplete\n      data={filteredResult}\n      value={searchText}\n      showClear\n      prefix={<IconSearch />}\n      placeholder={t(\"search\")}\n      emptyContent={<div className=\"p-3 popover-theme\">{t(\"not_found\")}</div>}\n      onSearch={(v) => handleStringSearch(v)}\n      onChange={(v) => setSearchText(v)}\n      onSelect={(v) => {\n        const { id } = notes.find((t) => t.title === v);\n        setActiveKey(`${id}`);\n        document\n          .getElementById(`scroll_note_${id}`)\n          .scrollIntoView({ behavior: \"smooth\" });\n      }}\n      className=\"w-full\"\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/RelationshipsTab/RelationshipInfo.jsx",
    "content": "import {\n  Row,\n  Col,\n  Select,\n  Button,\n  Popover,\n  Table,\n  Input,\n} from \"@douyinfe/semi-ui\";\nimport {\n  IconDeleteStroked,\n  IconLoopTextStroked,\n  IconMore,\n} from \"@douyinfe/semi-icons\";\nimport {\n  Cardinality,\n  Constraint,\n  Action,\n  ObjectType,\n} from \"../../../data/constants\";\nimport { useDiagram, useLayout, useUndoRedo } from \"../../../hooks\";\nimport i18n from \"../../../i18n/i18n\";\nimport { useTranslation } from \"react-i18next\";\nimport { useMemo, useState } from \"react\";\n\nconst columns = [\n  {\n    title: i18n.t(\"primary\"),\n    dataIndex: \"primary\",\n  },\n  {\n    title: i18n.t(\"foreign\"),\n    dataIndex: \"foreign\",\n  },\n];\n\nexport default function RelationshipInfo({ data }) {\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const { tables, deleteRelationship, updateRelationship } = useDiagram();\n  const { t } = useTranslation();\n  const { layout } = useLayout();\n  const [editField, setEditField] = useState({});\n\n  const relValues = useMemo(() => {\n    const { fields: startTableFields, name: startTableName } = tables.find(\n      (t) => t.id === data.startTableId,\n    );\n    const { name: startFieldName } = startTableFields.find(\n      (f) => f.id === data.startFieldId,\n    );\n    const { fields: endTableFields, name: endTableName } = tables.find(\n      (t) => t.id === data.endTableId,\n    );\n    const { name: endFieldName } = endTableFields.find(\n      (f) => f.id === data.endFieldId,\n    );\n    return {\n      startTableName,\n      startFieldName,\n      endTableName,\n      endFieldName,\n    };\n  }, [tables, data]);\n\n  const swapKeys = () => {\n    setUndoStack((prev) => [\n      ...prev,\n      {\n        action: Action.EDIT,\n        element: ObjectType.RELATIONSHIP,\n        rid: data.id,\n        undo: {\n          startTableId: data.startTableId,\n          startFieldId: data.startFieldId,\n          endTableId: data.endTableId,\n          endFieldId: data.endFieldId,\n        },\n        redo: {\n          startTableId: data.endTableId,\n          startFieldId: data.endFieldId,\n          endTableId: data.startTableId,\n          endFieldId: data.startFieldId,\n        },\n        message: t(\"edit_relationship\", {\n          refName: data.name,\n          extra: \"[swap keys]\",\n        }),\n      },\n    ]);\n    setRedoStack([]);\n\n    updateRelationship(data.id, {\n      name: `fk_${relValues.endTableName}_${relValues.endFieldName}_${relValues.startTableName}`,\n      startTableId: data.endTableId,\n      startFieldId: data.endFieldId,\n      endTableId: data.startTableId,\n      endFieldId: data.startFieldId,\n    });\n  };\n\n  const changeCardinality = (value) => {\n    if (layout.readOnly) return;\n\n    setUndoStack((prev) => [\n      ...prev,\n      {\n        action: Action.EDIT,\n        element: ObjectType.RELATIONSHIP,\n        rid: data.id,\n        undo: { cardinality: data.cardinality },\n        redo: { cardinality: value },\n        message: t(\"edit_relationship\", {\n          refName: data.name,\n          extra: \"[cardinality]\",\n        }),\n      },\n    ]);\n    setRedoStack([]);\n    updateRelationship(data.id, { cardinality: value });\n  };\n\n  const changeConstraint = (key, value) => {\n    if (layout.readOnly) return;\n\n    const undoKey = `${key}Constraint`;\n    setUndoStack((prev) => [\n      ...prev,\n      {\n        action: Action.EDIT,\n        element: ObjectType.RELATIONSHIP,\n        rid: data.id,\n        undo: { [undoKey]: data[undoKey] },\n        redo: { [undoKey]: value },\n        message: t(\"edit_relationship\", {\n          refName: data.name,\n          extra: \"[constraint]\",\n        }),\n      },\n    ]);\n    setRedoStack([]);\n    updateRelationship(data.id, { [undoKey]: value });\n  };\n\n  return (\n    <>\n      <div className=\"flex items-center mb-2.5\">\n        <div className=\"text-md font-semibold break-keep\">{t(\"name\")}: </div>\n        <Input\n          value={data.name}\n          validateStatus={data.name.trim() === \"\" ? \"error\" : \"default\"}\n          placeholder={t(\"name\")}\n          className=\"ms-2\"\n          readonly={layout.readOnly}\n          onChange={(value) => updateRelationship(data.id, { name: value })}\n          onFocus={(e) => setEditField({ name: e.target.value })}\n          onBlur={(e) => {\n            if (e.target.value === editField.name) return;\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.RELATIONSHIP,\n                component: \"self\",\n                rid: data.id,\n                undo: editField,\n                redo: { name: e.target.value },\n                message: t(\"edit_relationship\", {\n                  refName: e.target.value,\n                  extra: \"[name]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n          }}\n        />\n      </div>\n      <div className=\"flex justify-between items-center mb-3\">\n        <div className=\"me-3\">\n          <span className=\"font-semibold\">{t(\"primary\")}: </span>\n          {relValues.endTableName}\n        </div>\n        <div className=\"mx-1\">\n          <span className=\"font-semibold\">{t(\"foreign\")}: </span>\n          {relValues.startTableName}\n        </div>\n        <div className=\"ms-1\">\n          <Popover\n            content={\n              <div className=\"p-2 popover-theme\">\n                <Table\n                  columns={columns}\n                  dataSource={[\n                    {\n                      key: \"1\",\n                      foreign: `${relValues.startTableName}(${relValues.startFieldName})`,\n                      primary: `${relValues.endTableName}(${relValues.endFieldName})`,\n                    },\n                  ]}\n                  pagination={false}\n                  size=\"small\"\n                  bordered\n                />\n                <div className=\"mt-2\">\n                  <Button\n                    block\n                    icon={<IconLoopTextStroked />}\n                    onClick={swapKeys}\n                    disabled={layout.readOnly}\n                  >\n                    {t(\"swap\")}\n                  </Button>\n                </div>\n              </div>\n            }\n            trigger=\"click\"\n            position=\"rightTop\"\n            showArrow\n          >\n            <Button icon={<IconMore />} type=\"tertiary\" />\n          </Popover>\n        </div>\n      </div>\n      <div className=\"font-semibold my-1\">{t(\"cardinality\")}:</div>\n      <Select\n        optionList={Object.values(Cardinality).map((v) => ({\n          label: t(v),\n          value: v,\n        }))}\n        value={data.cardinality}\n        className=\"w-full\"\n        onChange={changeCardinality}\n      />\n\n      {data.cardinality !== Cardinality.ONE_TO_ONE && (\n        <>\n          <div className=\"text-md font-semibold break-keep mt-2\">\n            {t(\"many_side_label\")}:\n          </div>\n          <Input\n            value={data.manyLabel}\n            placeholder={t(\"label\")}\n            onChange={(value) => updateRelationship(data.id, { manyLabel: value })}\n            onFocus={(e) => setEditField({ manyLabel: e.target.value })}\n            readonly={layout.readOnly}\n            onBlur={(e) => {\n              if (e.target.value === editField.manyLabel) return;\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.RELATIONSHIP,\n                  component: \"self\",\n                  rid: data.id,\n                  undo: editField,\n                  redo: { manyLabel: e.target.value },\n                  message: t(\"edit_relationship\", {\n                    refName: e.target.value,\n                    extra: \"[manyLabel]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n            }}\n          />\n        </>\n      )}\n\n      <Row gutter={6} className=\"my-3\">\n        <Col span={12}>\n          <div className=\"font-semibold\">{t(\"on_update\")}: </div>\n          <Select\n            optionList={Object.values(Constraint).map((v) => ({\n              label: v,\n              value: v,\n            }))}\n            value={data.updateConstraint}\n            className=\"w-full\"\n            onChange={(value) => changeConstraint(\"update\", value)}\n          />\n        </Col>\n        <Col span={12}>\n          <div className=\"font-semibold\">{t(\"on_delete\")}: </div>\n          <Select\n            optionList={Object.values(Constraint).map((v) => ({\n              label: v,\n              value: v,\n            }))}\n            value={data.deleteConstraint}\n            className=\"w-full\"\n            onChange={(value) => changeConstraint(\"delete\", value)}\n          />\n        </Col>\n      </Row>\n      <Button\n        block\n        type=\"danger\"\n        disabled={layout.readOnly}\n        icon={<IconDeleteStroked />}\n        onClick={() => deleteRelationship(data.id)}\n      >\n        {t(\"delete\")}\n      </Button>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/RelationshipsTab/RelationshipsTab.jsx",
    "content": "import { Collapse } from \"@douyinfe/semi-ui\";\nimport { useSelect, useDiagram, useSaveState, useLayout } from \"../../../hooks\";\nimport Empty from \"../Empty\";\nimport SearchBar from \"./SearchBar\";\nimport RelationshipInfo from \"./RelationshipInfo\";\nimport { ObjectType, State } from \"../../../data/constants\";\nimport { useTranslation } from \"react-i18next\";\nimport { SortableList } from \"../../SortableList/SortableList\";\nimport { DragHandle } from \"../../SortableList/DragHandle\";\n\nexport default function RelationshipsTab() {\n  const { relationships, setRelationships } = useDiagram();\n  const { selectedElement, setSelectedElement } = useSelect();\n  const { setSaveState } = useSaveState();\n  const { layout } = useLayout();\n  const { t } = useTranslation();\n\n  return (\n    <>\n      <SearchBar />\n      {relationships.length <= 0 ? (\n        <Empty\n          title={t(\"no_relationships\")}\n          text={t(\"no_relationships_text\")}\n        />\n      ) : (\n        <Collapse\n          activeKey={\n            selectedElement.open &&\n            selectedElement.element === ObjectType.RELATIONSHIP\n              ? `${selectedElement.id}`\n              : \"\"\n          }\n          keepDOM={false}\n          lazyRender\n          onChange={(k) => {\n            setSelectedElement((prev) => ({\n              ...prev,\n              open: true,\n              id: k[0],\n              element: ObjectType.RELATIONSHIP,\n            }));\n          }}\n          accordion\n        >\n          <SortableList\n            keyPrefix=\"relationships-tab\"\n            items={relationships}\n            onChange={(newRelationships) => setRelationships(newRelationships)}\n            afterChange={() => setSaveState(State.SAVING)}\n            renderItem={(item) => (\n              <div id={`scroll_ref_${item.id}`} key={\"relationship_\" + item.id}>\n                <Collapse.Panel\n                  className=\"relative\"\n                  header={\n                    <div className=\"w-full flex items-center gap-2\">\n                      <DragHandle readOnly={layout.readOnly} id={item.id} />\n                      <div className=\"overflow-hidden text-ellipsis whitespace-nowrap\">\n                        {item.name}\n                      </div>\n                    </div>\n                  }\n                  itemKey={`${item.id}`}\n                >\n                  <RelationshipInfo data={item} />\n                </Collapse.Panel>\n              </div>\n            )}\n          />\n        </Collapse>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/RelationshipsTab/SearchBar.jsx",
    "content": "import { useState } from \"react\";\nimport { useSelect, useDiagram } from \"../../../hooks\";\nimport { AutoComplete } from \"@douyinfe/semi-ui\";\nimport { IconSearch } from \"@douyinfe/semi-icons\";\nimport { ObjectType } from \"../../../data/constants\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function SearchBar() {\n  const { relationships } = useDiagram();\n  const [searchText, setSearchText] = useState(\"\");\n  const { setSelectedElement } = useSelect();\n  const { t } = useTranslation();\n\n  const [filteredResult, setFilteredResult] = useState(\n    relationships.map((t) => t.name),\n  );\n\n  const handleStringSearch = (value) => {\n    setFilteredResult(\n      relationships.map((t) => t.name).filter((i) => i.includes(value)),\n    );\n  };\n\n  return (\n    <AutoComplete\n      data={filteredResult}\n      value={searchText}\n      showClear\n      prefix={<IconSearch />}\n      placeholder={t(\"search\")}\n      emptyContent={<div className=\"p-3 popover-theme\">{t(\"not_found\")}</div>}\n      onSearch={(v) => handleStringSearch(v)}\n      onChange={(v) => setSearchText(v)}\n      onSelect={(v) => {\n        const { id } = relationships.find((t) => t.name === v);\n        setSelectedElement((prev) => ({\n          ...prev,\n          id: id,\n          open: true,\n          element: ObjectType.RELATIONSHIP,\n        }));\n        document\n          .getElementById(`scroll_ref_${id}`)\n          .scrollIntoView({ behavior: \"smooth\" });\n      }}\n      className=\"w-full\"\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/SidePanel.jsx",
    "content": "import { useMemo } from \"react\";\nimport { Tabs, TabPane, Divider, Tooltip, Button } from \"@douyinfe/semi-ui\";\nimport { IconCode } from \"@douyinfe/semi-icons\";\nimport { Tab } from \"../../data/constants\";\nimport {\n  useLayout,\n  useSelect,\n  useDiagram,\n  useAreas,\n  useNotes,\n  useEnums,\n  useTypes,\n} from \"../../hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport RelationshipsTab from \"./RelationshipsTab/RelationshipsTab\";\nimport TypesTab from \"./TypesTab/TypesTab\";\nimport Issues from \"./Issues\";\nimport AreasTab from \"./AreasTab/AreasTab\";\nimport NotesTab from \"./NotesTab/NotesTab\";\nimport TablesTab from \"./TablesTab/TablesTab\";\nimport { databases } from \"../../data/databases\";\nimport EnumsTab from \"./EnumsTab/EnumsTab\";\nimport { isRtl } from \"../../i18n/utils/rtl\";\nimport i18n from \"../../i18n/i18n\";\nimport DBMLEditor from \"./DBMLEditor\";\n\nexport default function SidePanel({ width, resize, setResize }) {\n  const { layout, setLayout } = useLayout();\n  const { selectedElement, setSelectedElement } = useSelect();\n  const { database, tablesCount, relationshipsCount } = useDiagram();\n  const { areasCount } = useAreas();\n  const { notesCount } = useNotes();\n  const { typesCount } = useTypes();\n  const { enumsCount } = useEnums();\n  const { t } = useTranslation();\n\n  const toggleDBMLEditor = () => {\n    setLayout((prev) => ({ ...prev, dbmlEditor: !prev.dbmlEditor }));\n  };\n\n  const tabList = useMemo(() => {\n    const tabs = [\n      {\n        tab: `${t(\"tables\")} (${tablesCount})`,\n        itemKey: Tab.TABLES,\n        component: <TablesTab />,\n      },\n      {\n        tab: `${t(\"relationships\")} (${relationshipsCount})`,\n        itemKey: Tab.RELATIONSHIPS,\n        component: <RelationshipsTab />,\n      },\n      {\n        tab: `${t(\"subject_areas\")} (${areasCount})`,\n        itemKey: Tab.AREAS,\n        component: <AreasTab />,\n      },\n      {\n        tab: `${t(\"notes\")} (${notesCount})`,\n        itemKey: Tab.NOTES,\n        component: <NotesTab />,\n      },\n    ];\n\n    if (databases[database].hasTypes) {\n      tabs.push({\n        tab: `${t(\"types\")} (${typesCount})`,\n        itemKey: Tab.TYPES,\n        component: <TypesTab />,\n      });\n    }\n\n    if (databases[database].hasEnums) {\n      tabs.push({\n        tab: `${t(\"enums\")} (${enumsCount})`,\n        itemKey: Tab.ENUMS,\n        component: <EnumsTab />,\n      });\n    }\n\n    return isRtl(i18n.language) ? tabs.reverse() : tabs;\n  }, [\n    t,\n    database,\n    tablesCount,\n    relationshipsCount,\n    areasCount,\n    typesCount,\n    enumsCount,\n    notesCount,\n  ]);\n\n  return (\n    <div className=\"flex h-full\">\n      <div\n        className=\"flex flex-col h-full relative border-r border-color\"\n        style={{ width: `${width}px` }}\n      >\n        <div className=\"h-full flex-1 overflow-y-auto\">\n          {layout.dbmlEditor ? (\n            <DBMLEditor />\n          ) : (\n            <Tabs\n              type=\"card\"\n              activeKey={selectedElement.currentTab}\n              lazyRender\n              keepDOM={false}\n              onChange={(key) =>\n                setSelectedElement((prev) => ({ ...prev, currentTab: key }))\n              }\n              collapsible\n              tabBarStyle={{ direction: \"ltr\" }}\n              tabBarExtraContent={\n                <>\n                  <Divider layout=\"vertical\" />\n                  <Tooltip content={t(\"dbml_view\")} position=\"bottom\">\n                    <Button\n                      onClick={toggleDBMLEditor}\n                      icon={<IconCode />}\n                      theme=\"borderless\"\n                    />\n                  </Tooltip>\n                </>\n              }\n            >\n              {tabList.length &&\n                tabList.map((tab) => (\n                  <TabPane\n                    tab={tab.tab}\n                    itemKey={tab.itemKey}\n                    key={tab.itemKey}\n                  >\n                    <div className=\"p-2\">{tab.component}</div>\n                  </TabPane>\n                ))}\n            </Tabs>\n          )}\n        </div>\n        {layout.issues && (\n          <div className=\"mt-auto border-t-2 border-color shadow-inner\">\n            <Issues />\n          </div>\n        )}\n      </div>\n      <div\n        className={`flex justify-center items-center p-1 h-auto hover-2 cursor-col-resize ${\n          resize && \"bg-semi-grey-2\"\n        }`}\n        onPointerDown={(e) => e.isPrimary && setResize(true)}\n      >\n        <div className=\"w-1 border-x border-color h-1/6\" />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/TablesTab/FieldDetails.jsx",
    "content": "import { useMemo, useState } from \"react\";\nimport {\n  Input,\n  TextArea,\n  Button,\n  TagInput,\n  InputNumber,\n  Checkbox,\n} from \"@douyinfe/semi-ui\";\nimport { Action, ObjectType } from \"../../../data/constants\";\nimport { IconDeleteStroked } from \"@douyinfe/semi-icons\";\nimport { useDiagram, useLayout, useUndoRedo } from \"../../../hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport { dbToTypes } from \"../../../data/datatypes\";\nimport { databases } from \"../../../data/databases\";\n\nexport default function FieldDetails({ data, tid }) {\n  const { t } = useTranslation();\n  const { layout } = useLayout();\n  const { tables, database } = useDiagram();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const { updateField, deleteField } = useDiagram();\n  const [editField, setEditField] = useState({});\n  const table = useMemo(() => tables.find((t) => t.id === tid), [tables, tid]);\n\n  return (\n    <div>\n      <div className=\"font-semibold\">{t(\"default_value\")}</div>\n      <Input\n        className=\"my-2\"\n        placeholder={t(\"default_value\")}\n        value={data.default}\n        readonly={layout.readOnly}\n        disabled={dbToTypes[database][data.type].noDefault || data.increment}\n        onChange={(value) => updateField(tid, data.id, { default: value })}\n        onFocus={(e) => setEditField({ default: e.target.value })}\n        onBlur={(e) => {\n          if (e.target.value === editField.default) return;\n          setUndoStack((prev) => [\n            ...prev,\n            {\n              action: Action.EDIT,\n              element: ObjectType.TABLE,\n              component: \"field\",\n              tid: tid,\n              fid: data.id,\n              undo: editField,\n              redo: { default: e.target.value },\n              message: t(\"edit_table\", {\n                tableName: table.name,\n                extra: \"[field]\",\n              }),\n            },\n          ]);\n          setRedoStack([]);\n        }}\n      />\n      {(data.type === \"ENUM\" || data.type === \"SET\") && (\n        <>\n          <div className=\"font-semibold mb-1\">\n            {data.type} {t(\"values\")}\n          </div>\n          <TagInput\n            separator={[\",\", \", \", \" ,\"]}\n            value={data.values}\n            validateStatus={\n              !data.values || data.values.length === 0 ? \"error\" : \"default\"\n            }\n            addOnBlur\n            className=\"my-2\"\n            placeholder={t(\"use_for_batch_input\")}\n            onChange={(v) => {\n              if (layout.readOnly) return;\n              updateField(tid, data.id, { values: v });\n            }}\n            onFocus={() => setEditField({ values: data.values })}\n            onBlur={() => {\n              if (\n                JSON.stringify(editField.values) === JSON.stringify(data.values)\n              )\n                return;\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.TABLE,\n                  component: \"field\",\n                  tid: tid,\n                  fid: data.id,\n                  undo: editField,\n                  redo: { values: data.values },\n                  message: t(\"edit_table\", {\n                    tableName: table.name,\n                    extra: \"[field]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n            }}\n          />\n        </>\n      )}\n      {dbToTypes[database][data.type].isSized && (\n        <>\n          <div className=\"font-semibold\">{t(\"size\")}</div>\n          <InputNumber\n            className=\"my-2 w-full\"\n            placeholder={t(\"size\")}\n            value={data.size}\n            readonly={layout.readOnly}\n            onChange={(value) => updateField(tid, data.id, { size: value })}\n            onFocus={(e) => setEditField({ size: e.target.value })}\n            onBlur={(e) => {\n              if (e.target.value === editField.size) return;\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.TABLE,\n                  component: \"field\",\n                  tid: tid,\n                  fid: data.id,\n                  undo: editField,\n                  redo: { size: e.target.value },\n                  message: t(\"edit_table\", {\n                    tableName: table.name,\n                    extra: \"[field]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n            }}\n          />\n        </>\n      )}\n      {dbToTypes[database][data.type].hasPrecision && (\n        <>\n          <div className=\"font-semibold\">{t(\"precision\")}</div>\n          <Input\n            className=\"my-2 w-full\"\n            placeholder={t(\"set_precision\")}\n            validateStatus={\n              !data.size || /^\\d+,\\s*\\d+$|^$/.test(data.size)\n                ? \"default\"\n                : \"error\"\n            }\n            readonly={layout.readOnly}\n            value={data.size}\n            onChange={(value) => updateField(tid, data.id, { size: value })}\n            onFocus={(e) => setEditField({ size: e.target.value })}\n            onBlur={(e) => {\n              if (e.target.value === editField.size) return;\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.TABLE,\n                  component: \"field\",\n                  tid: tid,\n                  fid: data.id,\n                  undo: editField,\n                  redo: { size: e.target.value },\n                  message: t(\"edit_table\", {\n                    tableName: table.name,\n                    extra: \"[field]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n            }}\n          />\n        </>\n      )}\n      {dbToTypes[database][data.type].hasCheck && (\n        <>\n          <div className=\"font-semibold\">{t(\"check\")}</div>\n          <Input\n            className=\"mt-2\"\n            placeholder={t(\"check\")}\n            value={data.check}\n            disabled={data.increment}\n            readonly={layout.readOnly}\n            onChange={(value) => updateField(tid, data.id, { check: value })}\n            onFocus={(e) => setEditField({ check: e.target.value })}\n            onBlur={(e) => {\n              if (e.target.value === editField.check) return;\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.TABLE,\n                  component: \"field\",\n                  tid: tid,\n                  fid: data.id,\n                  undo: editField,\n                  redo: { check: e.target.value },\n                  message: t(\"edit_table\", {\n                    tableName: table.name,\n                    extra: \"[field]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n            }}\n          />\n          <div className=\"text-xs mt-1\">{t(\"this_will_appear_as_is\")}</div>\n        </>\n      )}\n      <div className=\"flex justify-between items-center my-3\">\n        <div className=\"font-medium\">{t(\"unique\")}</div>\n        <Checkbox\n          value=\"unique\"\n          checked={data.unique}\n          disabled={layout.readOnly}\n          onChange={(checkedValues) => {\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.TABLE,\n                component: \"field\",\n                tid: tid,\n                fid: data.id,\n                undo: {\n                  [checkedValues.target.value]: !checkedValues.target.checked,\n                },\n                redo: {\n                  [checkedValues.target.value]: checkedValues.target.checked,\n                },\n              },\n            ]);\n            setRedoStack([]);\n            updateField(tid, data.id, {\n              [checkedValues.target.value]: checkedValues.target.checked,\n            });\n          }}\n        />\n      </div>\n      <div className=\"flex justify-between items-center my-3\">\n        <div className=\"font-medium\">{t(\"autoincrement\")}</div>\n        <Checkbox\n          value=\"increment\"\n          checked={data.increment}\n          disabled={\n            !dbToTypes[database][data.type].canIncrement || data.isArray || layout.readOnly\n          }\n          onChange={(checkedValues) => {\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.TABLE,\n                component: \"field\",\n                tid: tid,\n                fid: data.id,\n                undo: {\n                  [checkedValues.target.value]: !checkedValues.target.checked,\n                },\n                redo: {\n                  [checkedValues.target.value]: checkedValues.target.checked,\n                },\n                message: t(\"edit_table\", {\n                  tableName: table.name,\n                  extra: \"[field]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n            updateField(tid, data.id, {\n              increment: !data.increment,\n              check: data.increment ? data.check : \"\",\n            });\n          }}\n        />\n      </div>\n      {databases[database].hasArrays && (\n        <div className=\"flex justify-between items-center my-3\">\n          <div className=\"font-medium\">{t(\"declare_array\")}</div>\n          <Checkbox\n            value=\"isArray\"\n            checked={data.isArray}\n            disabled={layout.readOnly}\n            onChange={(checkedValues) => {\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.TABLE,\n                  component: \"field\",\n                  tid: tid,\n                  fid: data.id,\n                  undo: {\n                    [checkedValues.target.value]: !checkedValues.target.checked,\n                  },\n                  redo: {\n                    [checkedValues.target.value]: checkedValues.target.checked,\n                  },\n                  message: t(\"edit_table\", {\n                    tableName: table.name,\n                    extra: \"[field]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n              updateField(tid, data.id, {\n                isArray: checkedValues.target.checked,\n                increment: data.isArray ? data.increment : false,\n              });\n            }}\n          />\n        </div>\n      )}\n      {databases[database].hasUnsignedTypes &&\n        dbToTypes[database][data.type].signed && (\n          <div className=\"flex justify-between items-center my-3\">\n            <div className=\"font-medium\">{t(\"Unsigned\")}</div>\n            <Checkbox\n              value=\"unsigned\"\n              checked={data.unsigned}\n              disabled={layout.readOnly}\n              onChange={(checkedValues) => {\n                setUndoStack((prev) => [\n                  ...prev,\n                  {\n                    action: Action.EDIT,\n                    element: ObjectType.TABLE,\n                    component: \"field\",\n                    tid: tid,\n                    fid: data.id,\n                    undo: {\n                      [checkedValues.target.value]:\n                        !checkedValues.target.checked,\n                    },\n                    redo: {\n                      [checkedValues.target.value]:\n                        checkedValues.target.checked,\n                    },\n                    message: t(\"edit_table\", {\n                      tableName: table.name,\n                      extra: \"[field]\",\n                    }),\n                  },\n                ]);\n                setRedoStack([]);\n                updateField(tid, data.id, {\n                  unsigned: checkedValues.target.checked,\n                });\n              }}\n            />\n          </div>\n        )}\n      <div className=\"font-semibold\">{t(\"comment\")}</div>\n      <TextArea\n        className=\"my-2\"\n        placeholder={t(\"comment\")}\n        value={data.comment}\n        readonly={layout.readOnly}\n        autosize\n        rows={2}\n        onChange={(value) => updateField(tid, data.id, { comment: value })}\n        onFocus={(e) => setEditField({ comment: e.target.value })}\n        onBlur={(e) => {\n          if (e.target.value === editField.comment) return;\n          setUndoStack((prev) => [\n            ...prev,\n            {\n              action: Action.EDIT,\n              element: ObjectType.TABLE,\n              component: \"field\",\n              tid: tid,\n              fid: data.id,\n              undo: editField,\n              redo: { comment: e.target.value },\n              message: t(\"edit_table\", {\n                tableName: table.name,\n                extra: \"[field]\",\n              }),\n            },\n          ]);\n          setRedoStack([]);\n        }}\n      />\n      <Button\n        icon={<IconDeleteStroked />}\n        type=\"danger\"\n        block\n        disabled={layout.readOnly}\n        onClick={() => deleteField(data, tid)}\n      >\n        {t(\"delete\")}\n      </Button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/TablesTab/IndexDetails.jsx",
    "content": "import { Action, ObjectType } from \"../../../data/constants\";\nimport { Input, Button, Popover, Checkbox, Select } from \"@douyinfe/semi-ui\";\nimport { IconMore, IconDeleteStroked } from \"@douyinfe/semi-icons\";\nimport { useDiagram, useLayout, useUndoRedo } from \"../../../hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport { useMemo, useState } from \"react\";\n\nexport default function IndexDetails({ data, fields, iid, tid }) {\n  const { t } = useTranslation();\n  const { layout } = useLayout();\n  const { tables, updateTable } = useDiagram();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const [editField, setEditField] = useState({});\n  const table = useMemo(() => tables.find((t) => t.id === tid), [tables, tid]);\n\n  return (\n    <div className=\"flex justify-between items-center mb-2\">\n      <Select\n        placeholder={t(\"select_fields\")}\n        multiple\n        validateStatus={data.fields.length === 0 ? \"error\" : \"default\"}\n        optionList={fields}\n        className=\"w-full\"\n        value={data.fields}\n        onChange={(value) => {\n          if (layout.readOnly) return;\n\n          setUndoStack((prev) => [\n            ...prev,\n            {\n              action: Action.EDIT,\n              element: ObjectType.TABLE,\n              component: \"index\",\n              tid: tid,\n              iid: iid,\n              undo: {\n                fields: [...data.fields],\n              },\n              redo: {\n                fields: [...value],\n              },\n              message: t(\"edit_table\", {\n                tableName: table.name,\n                extra: \"[index field]\",\n              }),\n            },\n          ]);\n          setRedoStack([]);\n          updateTable(tid, {\n            indices: table.indices.map((index) =>\n              index.id === iid\n                ? {\n                    ...index,\n                    fields: [...value],\n                  }\n                : index,\n            ),\n          });\n        }}\n      />\n      <Popover\n        content={\n          <div className=\"px-1 popover-theme\">\n            <div className=\"font-semibold mb-1\">{t(\"name\")}: </div>\n            <Input\n              value={data.name}\n              placeholder={t(\"name\")}\n              readonly={layout.readOnly}\n              validateStatus={data.name.trim() === \"\" ? \"error\" : \"default\"}\n              onFocus={() =>\n                setEditField({\n                  name: data.name,\n                })\n              }\n              onChange={(value) =>\n                updateTable(tid, {\n                  indices: table.indices.map((index) =>\n                    index.id === iid\n                      ? {\n                          ...index,\n                          name: value,\n                        }\n                      : index,\n                  ),\n                })\n              }\n              onBlur={(e) => {\n                if (e.target.value === editField.name) return;\n                setUndoStack((prev) => [\n                  ...prev,\n                  {\n                    action: Action.EDIT,\n                    element: ObjectType.TABLE,\n                    component: \"index\",\n                    tid: tid,\n                    iid: iid,\n                    undo: editField,\n                    redo: { name: e.target.value },\n                    message: t(\"edit_table\", {\n                      tableName: table.name,\n                      extra: \"[index]\",\n                    }),\n                  },\n                ]);\n                setRedoStack([]);\n              }}\n            />\n            <div className=\"flex justify-between items-center my-3\">\n              <div className=\"font-medium\">{t(\"unique\")}</div>\n              <Checkbox\n                value=\"unique\"\n                checked={data.unique}\n                disabled={layout.readOnly}\n                onChange={(checkedValues) => {\n                  setUndoStack((prev) => [\n                    ...prev,\n                    {\n                      action: Action.EDIT,\n                      element: ObjectType.TABLE,\n                      component: \"index\",\n                      tid: tid,\n                      iid: iid,\n                      undo: {\n                        [checkedValues.target.value]:\n                          !checkedValues.target.checked,\n                      },\n                      redo: {\n                        [checkedValues.target.value]:\n                          checkedValues.target.checked,\n                      },\n                      message: t(\"edit_table\", {\n                        tableName: table.name,\n                        extra: \"[index field]\",\n                      }),\n                    },\n                  ]);\n                  setRedoStack([]);\n                  updateTable(tid, {\n                    indices: table.indices.map((index) =>\n                      index.id === iid\n                        ? {\n                            ...index,\n                            [checkedValues.target.value]:\n                              checkedValues.target.checked,\n                          }\n                        : index,\n                    ),\n                  });\n                }}\n              ></Checkbox>\n            </div>\n            <Button\n              block\n              type=\"danger\"\n              disabled={layout.readOnly}\n              icon={<IconDeleteStroked />}\n              onClick={() => {\n                setUndoStack((prev) => [\n                  ...prev,\n                  {\n                    action: Action.EDIT,\n                    element: ObjectType.TABLE,\n                    component: \"index_delete\",\n                    tid: tid,\n                    data: data,\n                    message: t(\"edit_table\", {\n                      tableName: table.name,\n                      extra: \"[delete index]\",\n                    }),\n                  },\n                ]);\n                setRedoStack([]);\n                updateTable(tid, {\n                  indices: table.indices\n                    .filter((e) => e.id !== iid)\n                    .map((e, j) => ({\n                      ...e,\n                      id: j,\n                    })),\n                });\n              }}\n            >\n              {t(\"delete\")}\n            </Button>\n          </div>\n        }\n        trigger=\"click\"\n        position=\"rightTop\"\n        showArrow\n      >\n        <Button\n          icon={<IconMore />}\n          type=\"tertiary\"\n          style={{ marginLeft: \"12px\" }}\n        />\n      </Popover>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/TablesTab/SearchBar.jsx",
    "content": "import { useMemo } from \"react\";\nimport { useSelect } from \"../../../hooks\";\nimport { TreeSelect } from \"@douyinfe/semi-ui\";\nimport { IconSearch } from \"@douyinfe/semi-icons\";\nimport { ObjectType } from \"../../../data/constants\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function SearchBar({ tables }) {\n  const { setSelectedElement } = useSelect();\n  const { t } = useTranslation();\n\n  const treeData = useMemo(() => {\n    return tables.map(({ id, name: parentName, fields }, i) => {\n      const children = fields?.map(({ name }, j) => ({\n        tableId: id,\n        id: `${j}`,\n        label: name,\n        value: name,\n        key: `${i}-${j}`,\n      }));\n\n      return {\n        tableId: id,\n        id: `${i}`,\n        label: parentName,\n        value: parentName,\n        key: `${i}`,\n        children,\n      };\n    });\n  }, [tables]);\n\n  return (\n    <TreeSelect\n      searchPosition=\"trigger\"\n      dropdownStyle={{ maxHeight: 400, overflow: \"auto\" }}\n      treeData={treeData}\n      prefix={<IconSearch />}\n      emptyContent={<div className=\"p-3 popover-theme\">{t(\"not_found\")}</div>}\n      filterTreeNode\n      placeholder={t(\"search\")}\n      onChange={(node) => {\n        const { tableId, id, children } = node;\n\n        setSelectedElement((prev) => ({\n          ...prev,\n          id: tableId,\n          open: true,\n          element: ObjectType.TABLE,\n        }));\n        document\n          .getElementById(`scroll_table_${tableId}`)\n          .scrollIntoView({ behavior: \"smooth\" });\n\n        if (!children) {\n          document\n            .getElementById(`scroll_table_${tableId}_input_${id}`)\n            .focus();\n        }\n      }}\n      onChangeWithObject\n      className=\"w-full\"\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/TablesTab/TableField.jsx",
    "content": "import { useMemo, useState } from \"react\";\nimport { Action, ObjectType } from \"../../../data/constants\";\nimport { Input, Button, Popover, Select } from \"@douyinfe/semi-ui\";\nimport { IconMore, IconKeyStroked } from \"@douyinfe/semi-icons\";\nimport {\n  useEnums,\n  useDiagram,\n  useTypes,\n  useUndoRedo,\n  useLayout,\n} from \"../../../hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport { dbToTypes } from \"../../../data/datatypes\";\nimport { DragHandle } from \"../../SortableList/DragHandle\";\nimport FieldDetails from \"./FieldDetails\";\n\nexport default function TableField({ data, tid, index, inherited }) {\n  const { updateField } = useDiagram();\n  const { types } = useTypes();\n  const { enums } = useEnums();\n  const { layout } = useLayout();\n  const { tables, database } = useDiagram();\n  const { t } = useTranslation();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const [editField, setEditField] = useState({});\n  const table = useMemo(() => tables.find((t) => t.id === tid), [tables, tid]);\n\n  return (\n    <div className=\"hover-1 my-2 flex gap-2 items-center\">\n      <DragHandle readOnly={layout.readOnly} id={data.id} />\n\n      <div className=\"min-w-20 flex-1/3\">\n        <Input\n          value={data.name}\n          id={`scroll_table_${tid}_input_${index}`}\n          validateStatus={\n            data.name.trim() === \"\" || inherited ? \"error\" : \"default\"\n          }\n          readonly={layout.readOnly}\n          placeholder={t(\"name\")}\n          onChange={(value) => updateField(tid, data.id, { name: value })}\n          onFocus={(e) => setEditField({ name: e.target.value })}\n          onBlur={(e) => {\n            if (e.target.value === editField.name) return;\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.TABLE,\n                component: \"field\",\n                tid: tid,\n                fid: data.id,\n                undo: editField,\n                redo: { name: e.target.value },\n                message: t(\"edit_table\", {\n                  tableName: table.name,\n                  extra: \"[field]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n          }}\n        />\n      </div>\n\n      <div className=\"min-w-24 flex-1/3\">\n        <Select\n          className=\"w-full\"\n          optionList={[\n            ...Object.keys(dbToTypes[database]).map((value) => ({\n              label: value,\n              value,\n            })),\n            ...types.map((type) => ({\n              label: type.name.toUpperCase(),\n              value: type.name.toUpperCase(),\n            })),\n            ...enums.map((type) => ({\n              label: type.name.toUpperCase(),\n              value: type.name.toUpperCase(),\n            })),\n          ]}\n          filter\n          value={data.type}\n          validateStatus={data.type === \"\" ? \"error\" : \"default\"}\n          placeholder={t(\"type\")}\n          onChange={(value) => {\n            if (layout.readOnly) return;\n\n            if (value === data.type) return;\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.TABLE,\n                component: \"field\",\n                tid: tid,\n                fid: data.id,\n                undo: { type: data.type },\n                redo: { type: value },\n                message: t(\"edit_table\", {\n                  tableName: table.name,\n                  extra: \"[field]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n            const incr =\n              data.increment && !!dbToTypes[database][value].canIncrement;\n\n            if (value === \"ENUM\" || value === \"SET\") {\n              updateField(tid, data.id, {\n                type: value,\n                default: \"\",\n                values: data.values ? [...data.values] : [],\n                increment: incr,\n              });\n            } else if (\n              dbToTypes[database][value].isSized ||\n              dbToTypes[database][value].hasPrecision\n            ) {\n              updateField(tid, data.id, {\n                type: value,\n                size: dbToTypes[database][value].defaultSize,\n                increment: incr,\n              });\n            } else if (!dbToTypes[database][value].hasDefault || incr) {\n              updateField(tid, data.id, {\n                type: value,\n                increment: incr,\n                default: \"\",\n                size: \"\",\n                values: [],\n              });\n            } else if (dbToTypes[database][value].hasCheck) {\n              updateField(tid, data.id, {\n                type: value,\n                check: \"\",\n                increment: incr,\n              });\n            } else {\n              updateField(tid, data.id, {\n                type: value,\n                increment: incr,\n                size: \"\",\n                values: [],\n              });\n            }\n          }}\n        />\n      </div>\n\n      <div>\n        <Button\n          title={t(\"nullable\")}\n          type={data.notNull ? \"tertiary\" : \"primary\"}\n          theme={data.notNull ? \"light\" : \"solid\"}\n          onClick={() => {\n            if (layout.readOnly) return;\n\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.TABLE,\n                component: \"field\",\n                tid: tid,\n                fid: data.id,\n                undo: { notNull: data.notNull },\n                redo: { notNull: !data.notNull },\n                message: t(\"edit_table\", {\n                  tableName: table.name,\n                  extra: \"[field]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n            updateField(tid, data.id, { notNull: !data.notNull });\n          }}\n        >\n          ?\n        </Button>\n      </div>\n\n      <div>\n        <Button\n          title={t(\"primary\")}\n          theme={data.primary ? \"solid\" : \"light\"}\n          type={data.primary ? \"primary\" : \"tertiary\"}\n          icon={<IconKeyStroked />}\n          onClick={() => {\n            if (layout.readOnly) return;\n\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.TABLE,\n                component: \"field\",\n                tid: tid,\n                fid: data.id,\n                undo: { primary: data.primary },\n                redo: { primary: !data.primary },\n                message: t(\"edit_table\", {\n                  tableName: table.name,\n                  extra: \"[field]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n            updateField(tid, data.id, { primary: !data.primary });\n          }}\n        />\n      </div>\n\n      <div>\n        <Popover\n          content={\n            <div className=\"px-1 w-[240px] popover-theme\">\n              <FieldDetails data={data} tid={tid} />\n            </div>\n          }\n          trigger=\"click\"\n          position=\"right\"\n          showArrow\n        >\n          <Button type=\"tertiary\" icon={<IconMore />} />\n        </Popover>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/TablesTab/TableInfo.jsx",
    "content": "import { useState, useRef } from \"react\";\nimport {\n  Collapse,\n  Input,\n  TextArea,\n  Button,\n  Card,\n  Select,\n} from \"@douyinfe/semi-ui\";\nimport ColorPicker from \"../ColorPicker\";\nimport { IconDeleteStroked } from \"@douyinfe/semi-icons\";\nimport {\n  useDiagram,\n  useLayout,\n  useSaveState,\n  useUndoRedo,\n} from \"../../../hooks\";\nimport { Action, ObjectType, State, DB } from \"../../../data/constants\";\nimport TableField from \"./TableField\";\nimport IndexDetails from \"./IndexDetails\";\nimport { useTranslation } from \"react-i18next\";\nimport { SortableList } from \"../../SortableList/SortableList\";\nimport { nanoid } from \"nanoid\";\n\nexport default function TableInfo({ data }) {\n  const { tables, database } = useDiagram();\n  const { t } = useTranslation();\n  const [indexActiveKey, setIndexActiveKey] = useState(\"\");\n  const { layout } = useLayout();\n  const { deleteTable, updateTable, setTables } = useDiagram();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const { setSaveState } = useSaveState();\n  const [editField, setEditField] = useState({});\n  const initialColorRef = useRef(data.color);\n\n  const handleColorPick = (color) => {\n    setUndoStack((prev) => {\n      let undoColor = initialColorRef.current;\n      const lastColorChange = prev.findLast(\n        (e) =>\n          e.element === ObjectType.TABLE &&\n          e.tid === data.id &&\n          e.action === Action.EDIT &&\n          e.redo?.color,\n      );\n      if (lastColorChange) {\n        undoColor = lastColorChange.redo.color;\n      }\n\n      if (color === undoColor) return prev;\n\n      const newStack = [\n        ...prev,\n        {\n          action: Action.EDIT,\n          element: ObjectType.TABLE,\n          component: \"self\",\n          tid: data.id,\n          undo: { color: undoColor },\n          redo: { color: color },\n          message: t(\"edit_table\", {\n            tableName: data.name,\n            extra: \"[color]\",\n          }),\n        },\n      ];\n      return newStack;\n    });\n    setRedoStack([]);\n  };\n\n  const inheritedFieldNames =\n    Array.isArray(data.inherits) && data.inherits.length > 0\n      ? data.inherits\n          .map((parentName) => {\n            const parent = tables.find((t) => t.name === parentName);\n            return parent ? parent.fields.map((f) => f.name) : [];\n          })\n          .flat()\n      : [];\n\n  return (\n    <div>\n      <div className=\"flex items-center mb-2.5\">\n        <div className=\"text-md font-semibold break-keep\">{t(\"name\")}:</div>\n        <Input\n          value={data.name}\n          validateStatus={data.name.trim() === \"\" ? \"error\" : \"default\"}\n          placeholder={t(\"name\")}\n          className=\"ms-2\"\n          readonly={layout.readOnly}\n          onChange={(value) => updateTable(data.id, { name: value })}\n          onFocus={(e) => setEditField({ name: e.target.value })}\n          onBlur={(e) => {\n            if (e.target.value === editField.name) return;\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.TABLE,\n                component: \"self\",\n                tid: data.id,\n                undo: editField,\n                redo: { name: e.target.value },\n                message: t(\"edit_table\", {\n                  tableName: e.target.value,\n                  extra: \"[name]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n          }}\n        />\n      </div>\n\n      <SortableList\n        items={data.fields}\n        keyPrefix={`table-${data.id}`}\n        onChange={(newFields) =>\n          setTables((prev) =>\n            prev.map((t) =>\n              t.id === data.id ? { ...t, fields: newFields } : t,\n            ),\n          )\n        }\n        afterChange={() => setSaveState(State.SAVING)}\n        renderItem={(item, i) => (\n          <TableField\n            data={item}\n            tid={data.id}\n            index={i}\n            inherited={inheritedFieldNames.includes(item.name)}\n          />\n        )}\n      />\n\n      {database === DB.POSTGRES && (\n        <div className=\"mb-2\">\n          <div className=\"text-md font-semibold break-keep\">\n            {t(\"inherits\")}:\n          </div>\n          <Select\n            multiple\n            value={data.inherits || []}\n            optionList={tables\n              .filter((t) => t.id !== data.id)\n              .map((t) => ({ label: t.name, value: t.name }))}\n            onChange={(value) => {\n              if (layout.readOnly) return;\n\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.TABLE,\n                  component: \"self\",\n                  tid: data.id,\n                  undo: { inherits: data.inherits },\n                  redo: { inherits: value },\n                  message: t(\"edit_table\", {\n                    tableName: data.name,\n                    extra: \"[inherits]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n              updateTable(data.id, { inherits: value });\n            }}\n            placeholder={t(\"inherits\")}\n            className=\"w-full\"\n          />\n        </div>\n      )}\n\n      {data.indices.length > 0 && (\n        <Card\n          bodyStyle={{ padding: \"4px\" }}\n          style={{ marginTop: \"12px\", marginBottom: \"12px\" }}\n          headerLine={false}\n        >\n          <Collapse\n            activeKey={indexActiveKey}\n            keepDOM={false}\n            lazyRender\n            onChange={(itemKey) => setIndexActiveKey(itemKey)}\n            accordion\n          >\n            <Collapse.Panel header={t(\"indices\")} itemKey=\"1\">\n              {data.indices.map((idx, k) => (\n                <IndexDetails\n                  key={\"index_\" + k}\n                  data={idx}\n                  iid={k}\n                  tid={data.id}\n                  fields={data.fields.map((e) => ({\n                    value: e.name,\n                    label: e.name,\n                  }))}\n                />\n              ))}\n            </Collapse.Panel>\n          </Collapse>\n        </Card>\n      )}\n\n      <Card\n        bodyStyle={{ padding: \"4px\" }}\n        style={{ marginTop: \"12px\", marginBottom: \"12px\" }}\n        headerLine={false}\n      >\n        <Collapse keepDOM={false} lazyRender>\n          <Collapse.Panel header={t(\"comment\")} itemKey=\"1\">\n            <TextArea\n              field=\"comment\"\n              value={data.comment}\n              readonly={layout.readOnly}\n              autosize\n              placeholder={t(\"comment\")}\n              rows={1}\n              onChange={(value) =>\n                updateTable(data.id, { comment: value }, false)\n              }\n              onFocus={(e) => setEditField({ comment: e.target.value })}\n              onBlur={(e) => {\n                if (e.target.value === editField.comment) return;\n                setUndoStack((prev) => [\n                  ...prev,\n                  {\n                    action: Action.EDIT,\n                    element: ObjectType.TABLE,\n                    component: \"self\",\n                    tid: data.id,\n                    undo: editField,\n                    redo: { comment: e.target.value },\n                    message: t(\"edit_table\", {\n                      tableName: e.target.value,\n                      extra: \"[comment]\",\n                    }),\n                  },\n                ]);\n                setRedoStack([]);\n              }}\n            />\n          </Collapse.Panel>\n        </Collapse>\n      </Card>\n\n      <div className=\"flex justify-between items-center gap-1 mb-2\">\n        <ColorPicker\n          usePopover={true}\n          readOnly={layout.readOnly}\n          value={data.color}\n          onChange={(color) => updateTable(data.id, { color })}\n          onColorPick={(color) => handleColorPick(color)}\n        />\n        <div className=\"flex gap-1\">\n          <Button\n            block\n            disabled={layout.readOnly}\n            onClick={() => {\n              setIndexActiveKey(\"1\");\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.TABLE,\n                  component: \"index_add\",\n                  tid: data.id,\n                  message: t(\"edit_table\", {\n                    tableName: data.name,\n                    extra: \"[add index]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n              updateTable(data.id, {\n                indices: [\n                  ...data.indices,\n                  {\n                    id: data.indices.length,\n                    name: `${data.name}_index_${data.indices.length}`,\n                    unique: false,\n                    fields: [],\n                  },\n                ],\n              });\n            }}\n          >\n            {t(\"add_index\")}\n          </Button>\n          <Button\n            block\n            disabled={layout.readOnly}\n            onClick={() => {\n              const id = nanoid();\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.TABLE,\n                  component: \"field_add\",\n                  tid: data.id,\n                  fid: id,\n                  message: t(\"edit_table\", {\n                    tableName: data.name,\n                    extra: \"[add field]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n              updateTable(data.id, {\n                fields: [\n                  ...data.fields,\n                  {\n                    id,\n                    name: \"\",\n                    type: \"\",\n                    default: \"\",\n                    check: \"\",\n                    primary: false,\n                    unique: false,\n                    notNull: false,\n                    increment: false,\n                    comment: \"\",\n                  },\n                ],\n              });\n            }}\n          >\n            {t(\"add_field\")}\n          </Button>\n          <Button\n            type=\"danger\"\n            disabled={layout.readOnly}\n            icon={<IconDeleteStroked />}\n            onClick={() => deleteTable(data.id)}\n          />\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/TablesTab/TablesTab.jsx",
    "content": "import { Collapse, Button } from \"@douyinfe/semi-ui\";\nimport { IconEyeOpened, IconEyeClosed } from \"@douyinfe/semi-icons\";\nimport { IconPlus } from \"@douyinfe/semi-icons\";\nimport {\n  useSelect,\n  useDiagram,\n  useSaveState,\n  useLayout,\n  useUndoRedo,\n} from \"../../../hooks\";\nimport { Action, ObjectType, State } from \"../../../data/constants\";\nimport { useTranslation } from \"react-i18next\";\nimport { DragHandle } from \"../../SortableList/DragHandle\";\nimport { SortableList } from \"../../SortableList/SortableList\";\nimport SearchBar from \"./SearchBar\";\nimport Empty from \"../Empty\";\nimport TableInfo from \"./TableInfo\";\n\nexport default function TablesTab() {\n  const { tables, addTable, setTables } = useDiagram();\n  const { selectedElement, setSelectedElement } = useSelect();\n  const { t } = useTranslation();\n  const { layout } = useLayout();\n  const { setSaveState } = useSaveState();\n\n  return (\n    <>\n      <div className=\"flex gap-2\">\n        <SearchBar tables={tables} />\n        <div>\n          <Button\n            block\n            icon={<IconPlus />}\n            onClick={() => addTable()}\n            disabled={layout.readOnly}\n          >\n            {t(\"add_table\")}\n          </Button>\n        </div>\n      </div>\n      {tables.length === 0 ? (\n        <Empty title={t(\"no_tables\")} text={t(\"no_tables_text\")} />\n      ) : (\n        <Collapse\n          activeKey={\n            selectedElement.open && selectedElement.element === ObjectType.TABLE\n              ? `${selectedElement.id}`\n              : \"\"\n          }\n          keepDOM={false}\n          lazyRender\n          onChange={(k) =>\n            setSelectedElement((prev) => ({\n              ...prev,\n              open: true,\n              id: k[0],\n              element: ObjectType.TABLE,\n            }))\n          }\n          accordion\n        >\n          <SortableList\n            keyPrefix=\"tables-tab\"\n            items={tables}\n            onChange={(newTables) => setTables(newTables)}\n            afterChange={() => setSaveState(State.SAVING)}\n            renderItem={(item) => <TableListItem table={item} />}\n          />\n        </Collapse>\n      )}\n    </>\n  );\n}\n\nfunction TableListItem({ table }) {\n  const { layout } = useLayout();\n  const { updateTable } = useDiagram();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const { t } = useTranslation();\n\n  const toggleTableVisibility = (e) => {\n    e.stopPropagation();\n    setUndoStack((prev) => [\n      ...prev,\n      {\n        action: Action.EDIT,\n        element: ObjectType.TABLE,\n        component: \"self\",\n        tid: table.id,\n        undo: { hidden: table.hidden },\n        redo: { hidden: !table.hidden },\n        message: t(\"edit_table\", {\n          tableName: table.name,\n          extra: \"[hidden]\",\n        }),\n      },\n    ]);\n    setRedoStack([]);\n    updateTable(table.id, { hidden: !table.hidden });\n  };\n\n  return (\n    <div id={`scroll_table_${table.id}`}>\n      <Collapse.Panel\n        className=\"relative\"\n        header={\n          <div className=\"flex items-center justify-between w-full\">\n            <div className=\"flex items-center gap-2 flex-1\">\n              <DragHandle readOnly={layout.readOnly} id={table.id} />\n              <div className=\"overflow-hidden text-ellipsis whitespace-nowrap\">\n                {table.name}\n              </div>\n            </div>\n            <Button\n              size=\"small\"\n              theme=\"borderless\"\n              type=\"tertiary\"\n              onClick={toggleTableVisibility}\n              icon={table.hidden ? <IconEyeClosed /> : <IconEyeOpened />}\n              className=\"me-2\"\n            />\n            <div\n              className=\"w-1 h-full absolute top-0 left-0 bottom-0\"\n              style={{ backgroundColor: table.color }}\n            />\n          </div>\n        }\n        itemKey={`${table.id}`}\n      >\n        <TableInfo data={table} />\n      </Collapse.Panel>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/TypesTab/SearchBar.jsx",
    "content": "import { useState } from \"react\";\nimport { AutoComplete } from \"@douyinfe/semi-ui\";\nimport { IconSearch } from \"@douyinfe/semi-icons\";\nimport { useSelect, useTypes } from \"../../../hooks\";\nimport { ObjectType } from \"../../../data/constants\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function Searchbar() {\n  const { types } = useTypes();\n  const [value, setValue] = useState(\"\");\n  const { setSelectedElement } = useSelect();\n  const { t } = useTranslation();\n\n  const [filteredResult, setFilteredResult] = useState(\n    types.map((t) => t.name),\n  );\n\n  const handleStringSearch = (value) => {\n    setFilteredResult(\n      types.map((t) => t.name).filter((i) => i.includes(value)),\n    );\n  };\n\n  return (\n    <AutoComplete\n      data={filteredResult}\n      value={value}\n      showClear\n      prefix={<IconSearch />}\n      placeholder={t(\"search\")}\n      onSearch={(v) => handleStringSearch(v)}\n      emptyContent={<div className=\"p-3 popover-theme\">{t(\"not_found\")}</div>}\n      onChange={(v) => setValue(v)}\n      onSelect={(v) => {\n        const i = types.findIndex((t) => t.name === v);\n        setSelectedElement((prev) => ({\n          ...prev,\n          id: i,\n          open: true,\n          element: ObjectType.TYPE,\n        }));\n        document\n          .getElementById(`scroll_type_${i}`)\n          .scrollIntoView({ behavior: \"smooth\" });\n      }}\n      className=\"w-full\"\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/TypesTab/TypeField.jsx",
    "content": "import { useState } from \"react\";\nimport { Action, ObjectType } from \"../../../data/constants\";\nimport {\n  Row,\n  Col,\n  Input,\n  Button,\n  Select,\n  TagInput,\n  InputNumber,\n  Popover,\n} from \"@douyinfe/semi-ui\";\nimport { IconDeleteStroked, IconMore } from \"@douyinfe/semi-icons\";\nimport {\n  useUndoRedo,\n  useTypes,\n  useDiagram,\n  useEnums,\n  useLayout,\n} from \"../../../hooks\";\nimport { useTranslation } from \"react-i18next\";\nimport { dbToTypes } from \"../../../data/datatypes\";\n\nexport default function TypeField({ data, tid, fid }) {\n  const { types, updateType } = useTypes();\n  const { enums } = useEnums();\n  const { layout } = useLayout();\n  const { database } = useDiagram();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const [editField, setEditField] = useState({});\n  const { t } = useTranslation();\n\n  return (\n    <Row gutter={6} className=\"hover-1 my-2\">\n      <Col span={10}>\n        <Input\n          value={data.name}\n          readonly={layout.readOnly}\n          validateStatus={data.name === \"\" ? \"error\" : \"default\"}\n          placeholder={t(\"name\")}\n          onChange={(value) =>\n            updateType(tid, {\n              fields: types[tid].fields.map((e, id) =>\n                id === fid ? { ...data, name: value } : e,\n              ),\n            })\n          }\n          onFocus={(e) => setEditField({ name: e.target.value })}\n          onBlur={(e) => {\n            if (e.target.value === editField.name) return;\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.TYPE,\n                component: \"field\",\n                tid: tid,\n                fid: fid,\n                undo: editField,\n                redo: { name: e.target.value },\n                message: t(\"edit_type\", {\n                  typeName: data.name,\n                  extra: \"[field]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n          }}\n        />\n      </Col>\n      <Col span={11}>\n        <Select\n          className=\"w-full\"\n          optionList={[\n            ...Object.keys(dbToTypes[database]).map((value) => ({\n              label: value,\n              value: value,\n            })),\n            ...types\n              .filter(\n                (type) => type.name.toLowerCase() !== types[tid].name.toLowerCase(),\n              )\n              .map((type) => ({\n                label: type.name.toUpperCase(),\n                value: type.name.toUpperCase(),\n              })),\n            ...enums.map((type) => ({\n              label: type.name.toUpperCase(),\n              value: type.name.toUpperCase(),\n            })),\n          ]}\n          filter\n          value={data.type}\n          validateStatus={data.type === \"\" ? \"error\" : \"default\"}\n          placeholder={t(\"type\")}\n          onChange={(value) => {\n            if (layout.readOnly) return;\n            if (value === data.type) return;\n            setUndoStack((prev) => [\n              ...prev,\n              {\n                action: Action.EDIT,\n                element: ObjectType.TYPE,\n                component: \"field\",\n                tid: tid,\n                fid: fid,\n                undo: { type: data?.type },\n                redo: { type: value },\n                message: t(\"edit_type\", {\n                  typeName: data.name,\n                  extra: \"[field]\",\n                }),\n              },\n            ]);\n            setRedoStack([]);\n            if (value === \"ENUM\" || value === \"SET\") {\n              updateType(tid, {\n                fields: types[tid].fields?.map((e, id) =>\n                  id === fid\n                    ? {\n                        ...data,\n                        type: value,\n                        values: data.values ? [...data.values] : [],\n                      }\n                    : e,\n                ),\n              });\n            } else if (\n              dbToTypes[database][value].isSized ||\n              dbToTypes[database][value].hasPrecision\n            ) {\n              updateType(tid, {\n                fields: types[tid].fields.map((e, id) =>\n                  id === fid\n                    ? {\n                        ...data,\n                        type: value,\n                        size: dbToTypes[database][value].defaultSize,\n                      }\n                    : e,\n                ),\n              });\n            } else {\n              updateType(tid, {\n                fields: types[tid].fields.map((e, id) =>\n                  id === fid ? { ...data, type: value } : e,\n                ),\n              });\n            }\n          }}\n        />\n      </Col>\n      <Col span={3}>\n        <Popover\n          content={\n            <div className=\"popover-theme w-[240px]\">\n              {(data.type === \"ENUM\" || data.type === \"SET\") && (\n                <>\n                  <div className=\"font-semibold mb-1\">\n                    {data.type} {t(\"values\")}\n                  </div>\n                  <TagInput\n                    separator={[\",\", \", \", \" ,\"]}\n                    value={data.values}\n                    validateStatus={\n                      !data.values || data.values.length === 0\n                        ? \"error\"\n                        : \"default\"\n                    }\n                    className=\"my-2\"\n                    placeholder={t(\"use_for_batch_input\")}\n                    onChange={(v) => {\n                      if (layout.readOnly) return;\n                      updateType(tid, {\n                        fields: types[tid].fields.map((e, id) =>\n                          id === fid ? { ...data, values: v } : e,\n                        ),\n                      });\n                    }}\n                    onFocus={() => setEditField({ values: data.values })}\n                    onBlur={() => {\n                      if (\n                        JSON.stringify(editField.values) ===\n                        JSON.stringify(data.values)\n                      )\n                        return;\n                      setUndoStack((prev) => [\n                        ...prev,\n                        {\n                          action: Action.EDIT,\n                          element: ObjectType.TYPE,\n                          component: \"field\",\n                          tid: tid,\n                          fid: fid,\n                          undo: editField,\n                          redo: { values: data.values },\n                          message: t(\"edit_type\", {\n                            typeName: data.name,\n                            extra: \"[field]\",\n                          }),\n                        },\n                      ]);\n                      setRedoStack([]);\n                    }}\n                  />\n                </>\n              )}\n              {dbToTypes[database][data.type].isSized && (\n                <>\n                  <div className=\"font-semibold\">{t(\"size\")}</div>\n                  <InputNumber\n                    className=\"my-2 w-full\"\n                    placeholder={t(\"size\")}\n                    value={data.size}\n                    readonly={layout.readOnly}\n                    onChange={(value) =>\n                      updateType(tid, {\n                        fields: types[tid].fields.map((e, id) =>\n                          id === fid ? { ...data, size: value } : e,\n                        ),\n                      })\n                    }\n                    onFocus={(e) => setEditField({ size: e.target.value })}\n                    onBlur={(e) => {\n                      if (e.target.value === editField.size) return;\n                      setUndoStack((prev) => [\n                        ...prev,\n                        {\n                          action: Action.EDIT,\n                          element: ObjectType.TABLE,\n                          component: \"field\",\n                          tid: tid,\n                          fid: fid,\n                          undo: editField,\n                          redo: { size: e.target.value },\n                          message: t(\"edit_type\", {\n                            typeName: data.name,\n                            extra: \"[field]\",\n                          }),\n                        },\n                      ]);\n                      setRedoStack([]);\n                    }}\n                  />\n                </>\n              )}\n              {dbToTypes[database][data.type].hasPrecision && (\n                <>\n                  <div className=\"font-semibold\">{t(\"precision\")}</div>\n                  <Input\n                    className=\"my-2 w-full\"\n                    placeholder={t(\"set_precision\")}\n                    readonly={layout.readOnly}\n                    validateStatus={\n                      /^\\(\\d+,\\s*\\d+\\)$|^$/.test(data.size)\n                        ? \"default\"\n                        : \"error\"\n                    }\n                    value={data.size}\n                    onChange={(value) =>\n                      updateType(tid, {\n                        fields: types[tid].fields.map((e, id) =>\n                          id === fid ? { ...data, size: value } : e,\n                        ),\n                      })\n                    }\n                    onFocus={(e) => setEditField({ size: e.target.value })}\n                    onBlur={(e) => {\n                      if (e.target.value === editField.size) return;\n                      setUndoStack((prev) => [\n                        ...prev,\n                        {\n                          action: Action.EDIT,\n                          element: ObjectType.TABLE,\n                          component: \"field\",\n                          tid: tid,\n                          fid: fid,\n                          undo: editField,\n                          redo: { size: e.target.value },\n                          message: t(\"edit_type\", {\n                            typeName: data.name,\n                            extra: \"[field]\",\n                          }),\n                        },\n                      ]);\n                      setRedoStack([]);\n                    }}\n                  />\n                </>\n              )}\n              <Button\n                block\n                type=\"danger\"\n                disabled={layout.readOnly}\n                icon={<IconDeleteStroked />}\n                onClick={() => {\n                  setUndoStack((prev) => [\n                    ...prev,\n                    {\n                      action: Action.EDIT,\n                      element: ObjectType.TYPE,\n                      component: \"field_delete\",\n                      tid: tid,\n                      fid: fid,\n                      data: data,\n                      message: t(\"edit_type\", {\n                        typeName: data.name,\n                        extra: \"[delete field]\",\n                      }),\n                    },\n                  ]);\n                  updateType(tid, {\n                    fields: types[tid].fields.filter((_, k) => k !== fid),\n                  });\n                }}\n              >\n                {t(\"delete\")}\n              </Button>\n            </div>\n          }\n          showArrow\n          trigger=\"click\"\n          position=\"right\"\n        >\n          <Button icon={<IconMore />} type=\"tertiary\" />\n        </Popover>\n      </Col>\n    </Row>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/TypesTab/TypeInfo.jsx",
    "content": "import { useState } from \"react\";\nimport { Action, ObjectType } from \"../../../data/constants\";\nimport {\n  Collapse,\n  Row,\n  Col,\n  Input,\n  TextArea,\n  Button,\n  Card,\n} from \"@douyinfe/semi-ui\";\nimport { IconDeleteStroked, IconPlus } from \"@douyinfe/semi-icons\";\nimport { useUndoRedo, useTypes, useDiagram, useLayout } from \"../../../hooks\";\nimport TypeField from \"./TypeField\";\nimport { useTranslation } from \"react-i18next\";\nimport { nanoid } from \"nanoid\";\n\nexport default function TypeInfo({ index, data }) {\n  const { layout } = useLayout();\n  const { deleteType, updateType } = useTypes();\n  const { tables, updateField } = useDiagram();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const [editField, setEditField] = useState({});\n  const { t } = useTranslation();\n\n  // TODO: remove indexes, not a valid case after adding id to types\n  const typeId = data.id ?? index;\n\n  return (\n    <div id={`scroll_type_${typeId}`}>\n      <Collapse.Panel\n        header={\n          <div className=\"overflow-hidden text-ellipsis whitespace-nowrap\">\n            {data.name}\n          </div>\n        }\n        itemKey={`${index}`}\n      >\n        <div className=\"flex items-center mb-2.5\">\n          <div className=\"text-md font-semibold break-keep\">{t(\"name\")}: </div>\n          <Input\n            value={data.name}\n            readonly={layout.readOnly}\n            validateStatus={data.name === \"\" ? \"error\" : \"default\"}\n            placeholder={t(\"name\")}\n            className=\"ms-2\"\n            onChange={(value) => {\n              updateType(typeId, { name: value });\n              tables.forEach((table) => {\n                table.fields.forEach((field) => {\n                  if (field.type.toLowerCase() === data.name.toLowerCase()) {\n                    updateField(table.id, field.id, {\n                      type: value.toUpperCase(),\n                    });\n                  }\n                });\n              });\n            }}\n            onFocus={(e) => setEditField({ name: e.target.value })}\n            onBlur={(e) => {\n              if (e.target.value === editField.name) return;\n\n              const updatedFields = tables.reduce((acc, table) => {\n                table.fields.forEach((field, i) => {\n                  if (field.type.toLowerCase() === data.name.toLowerCase()) {\n                    acc.push({ tid: table.id, fid: i });\n                  }\n                });\n                return acc;\n              }, []);\n\n              setUndoStack((prev) => [\n                ...prev,\n                {\n                  action: Action.EDIT,\n                  element: ObjectType.TYPE,\n                  component: \"self\",\n                  tid: typeId,\n                  undo: editField,\n                  redo: { name: e.target.value },\n                  updatedFields,\n                  message: t(\"edit_type\", {\n                    typeName: data.name,\n                    extra: \"[name]\",\n                  }),\n                },\n              ]);\n              setRedoStack([]);\n            }}\n          />\n        </div>\n        {data.fields.map((f, j) => (\n          <TypeField key={j} data={f} fid={j} tid={index} />\n        ))}\n        <Card\n          bodyStyle={{ padding: \"4px\" }}\n          style={{ marginTop: \"12px\", marginBottom: \"12px\" }}\n          headerLine={false}\n        >\n          <Collapse lazyRender keepDOM={false}>\n            <Collapse.Panel header={t(\"comment\")} itemKey=\"1\">\n              <TextArea\n                field=\"comment\"\n                value={data.comment}\n                autosize\n                readonly={layout.readOnly}\n                placeholder={t(\"comment\")}\n                rows={1}\n                onChange={(value) =>\n                  updateType(typeId, { comment: value }, false)\n                }\n                onFocus={(e) => setEditField({ comment: e.target.value })}\n                onBlur={(e) => {\n                  if (e.target.value === editField.comment) return;\n                  setUndoStack((prev) => [\n                    ...prev,\n                    {\n                      action: Action.EDIT,\n                      element: ObjectType.TYPE,\n                      component: \"self\",\n                      tid: typeId,\n                      undo: editField,\n                      redo: { comment: e.target.value },\n                      message: t(\"edit_type\", {\n                        typeName: data.name,\n                        extra: \"[comment]\",\n                      }),\n                    },\n                  ]);\n                  setRedoStack([]);\n                }}\n              />\n            </Collapse.Panel>\n          </Collapse>\n        </Card>\n        <Row gutter={6} className=\"mt-2\">\n          <Col span={12}>\n            <Button\n              icon={<IconPlus />}\n              disabled={layout.readOnly}\n              onClick={() => {\n                const newField = {\n                  name: \"\",\n                  type: \"\",\n                  id: nanoid(),\n                };\n                setUndoStack((prev) => [\n                  ...prev,\n                  {\n                    action: Action.EDIT,\n                    element: ObjectType.TYPE,\n                    component: \"field_add\",\n                    data: {\n                      field: newField,\n                      index: data.fields.length,\n                    },\n                    tid: typeId,\n                    message: t(\"edit_type\", {\n                      typeName: data.name,\n                      extra: \"[add field]\",\n                    }),\n                  },\n                ]);\n                setRedoStack([]);\n                updateType(typeId, {\n                  fields: [...data.fields, newField],\n                });\n              }}\n              block\n            >\n              {t(\"add_field\")}\n            </Button>\n          </Col>\n          <Col span={12}>\n            <Button\n              block\n              type=\"danger\"\n              disabled={layout.readOnly}\n              icon={<IconDeleteStroked />}\n              onClick={() => deleteType(typeId)}\n            >\n              {t(\"delete\")}\n            </Button>\n          </Col>\n        </Row>\n      </Collapse.Panel>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorSidePanel/TypesTab/TypesTab.jsx",
    "content": "import { Collapse, Button, Popover } from \"@douyinfe/semi-ui\";\nimport { IconPlus, IconInfoCircle } from \"@douyinfe/semi-icons\";\nimport { useSelect, useDiagram, useTypes, useLayout } from \"../../../hooks\";\nimport { DB, ObjectType } from \"../../../data/constants\";\nimport Searchbar from \"./SearchBar\";\nimport Empty from \"../Empty\";\nimport TypeInfo from \"./TypeInfo\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function TypesTab() {\n  const { types, addType } = useTypes();\n  const { selectedElement, setSelectedElement } = useSelect();\n  const { layout } = useLayout();\n  const { database } = useDiagram();\n  const { t } = useTranslation();\n\n  return (\n    <>\n      <div className=\"flex gap-2\">\n        <Searchbar />\n        <div>\n          <Button\n            block\n            icon={<IconPlus />}\n            onClick={() => addType()}\n            disabled={layout.readOnly}\n          >\n            {t(\"add_type\")}\n          </Button>\n        </div>\n        {database === DB.GENERIC && (\n          <Popover\n            content={\n              <div className=\"w-[240px] text-sm space-y-2 popover-theme\">\n                {t(\"types_info\")\n                  .split(\"\\n\")\n                  .map((line, index) => (\n                    <div key={index}>{line}</div>\n                  ))}\n              </div>\n            }\n            showArrow\n            position=\"rightTop\"\n          >\n            <Button theme=\"borderless\" icon={<IconInfoCircle />} />\n          </Popover>\n        )}\n      </div>\n      {types.length <= 0 ? (\n        <Empty title={t(\"no_types\")} text={t(\"no_types_text\")} />\n      ) : (\n        <Collapse\n          activeKey={\n            selectedElement.open && selectedElement.element === ObjectType.TYPE\n              ? `${selectedElement.id}`\n              : \"\"\n          }\n          keepDOM={false}\n          lazyRender\n          onChange={(id) =>\n            setSelectedElement((prev) => ({\n              ...prev,\n              open: true,\n              id: parseInt(id),\n              element: ObjectType.TYPE,\n            }))\n          }\n          accordion\n        >\n          {types.map((t, i) => (\n            <TypeInfo data={t} key={i} index={i} />\n          ))}\n        </Collapse>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/FloatingControls.jsx",
    "content": "import { Divider, Tooltip } from \"@douyinfe/semi-ui\";\nimport { useTransform, useLayout } from \"../hooks\";\nimport { exitFullscreen } from \"../utils/fullscreen\";\nimport { useTranslation } from \"react-i18next\";\n\nexport default function FloatingControls() {\n  const { transform, setTransform } = useTransform();\n  const { setLayout } = useLayout();\n  const { t } = useTranslation();\n\n  return (\n    <div className=\"flex gap-2\">\n      <div className=\"popover-theme flex rounded-lg items-center\">\n        <button\n          className=\"px-3 py-2\"\n          onClick={() =>\n            setTransform((prev) => ({\n              ...prev,\n              zoom: prev.zoom / 1.2,\n            }))\n          }\n        >\n          <i className=\"bi bi-dash-lg\" />\n        </button>\n        <Divider align=\"center\" layout=\"vertical\" />\n        <div className=\"px-3 py-2\">{parseInt(transform.zoom * 100)}%</div>\n        <Divider align=\"center\" layout=\"vertical\" />\n        <button\n          className=\"px-3 py-2\"\n          onClick={() =>\n            setTransform((prev) => ({\n              ...prev,\n              zoom: prev.zoom * 1.2,\n            }))\n          }\n        >\n          <i className=\"bi bi-plus-lg\" />\n        </button>\n      </div>\n      <Tooltip content={t(\"exit\")}>\n        <button\n          className=\"px-3 py-2 rounded-lg popover-theme\"\n          onClick={() => {\n            setLayout((prev) => ({\n              ...prev,\n              sidebar: true,\n              toolbar: true,\n              header: true,\n            }));\n            exitFullscreen();\n          }}\n        >\n          <i className=\"bi bi-fullscreen-exit\" />\n        </button>\n      </Tooltip>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/LexicalEditor/AutoLinkPlugin.jsx",
    "content": "/**\n * See https://codesandbox.io/p/sandbox/vigilant-kate-5tncvy?file=%2Fsrc%2Fplugins%2FAutoLinkPlugin.js\n*/\n\nimport { AutoLinkPlugin } from \"@lexical/react/LexicalAutoLinkPlugin\";\n\nconst URL_MATCHER =\n  /((https?:\\/\\/(www\\.)?)|(www\\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;\n\nconst EMAIL_MATCHER =\n  /(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))/;\n\nconst MATCHERS = [\n  (text) => {\n    const match = URL_MATCHER.exec(text);\n    return (\n      match && {\n        index: match.index,\n        length: match[0].length,\n        text: match[0],\n        url: match[0],\n      }\n    );\n  },\n  (text) => {\n    const match = EMAIL_MATCHER.exec(text);\n    return (\n      match && {\n        index: match.index,\n        length: match[0].length,\n        text: match[0],\n        url: `mailto:${match[0]}`,\n      }\n    );\n  },\n];\n\nexport default function PlaygroundAutoLinkPlugin() {\n  return <AutoLinkPlugin matchers={MATCHERS} />;\n}\n"
  },
  {
    "path": "src/components/LexicalEditor/CodeHighlightPlugin.jsx",
    "content": "/**\n * See https://codesandbox.io/p/sandbox/vigilant-kate-5tncvy?file=%2Fsrc%2Fplugins%2FCodeHighlightPlugin.js\n */\n\nimport { registerCodeHighlighting } from \"@lexical/code\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { useEffect } from \"react\";\n\nexport default function CodeHighlightPlugin() {\n  const [editor] = useLexicalComposerContext();\n  useEffect(() => {\n    return registerCodeHighlighting(editor);\n  }, [editor]);\n  return null;\n}\n"
  },
  {
    "path": "src/components/LexicalEditor/ListMaxIndentLevelPlugin.jsx",
    "content": "/**\n * See https://codesandbox.io/p/sandbox/vigilant-kate-5tncvy?file=%2Fsrc%2Fplugins%2FListMaxIndentLevelPlugin.js\n */\n\nimport { $getListDepth, $isListItemNode, $isListNode } from \"@lexical/list\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n  $getSelection,\n  $isElementNode,\n  $isRangeSelection,\n  INDENT_CONTENT_COMMAND,\n  COMMAND_PRIORITY_HIGH,\n} from \"lexical\";\nimport { useEffect } from \"react\";\n\nfunction getElementNodesInSelection(selection) {\n  const nodesInSelection = selection.getNodes();\n\n  if (nodesInSelection.length === 0) {\n    return new Set([\n      selection.anchor.getNode().getParentOrThrow(),\n      selection.focus.getNode().getParentOrThrow(),\n    ]);\n  }\n\n  return new Set(\n    nodesInSelection.map((n) => ($isElementNode(n) ? n : n.getParentOrThrow()))\n  );\n}\n\nfunction isIndentPermitted(maxDepth) {\n  const selection = $getSelection();\n\n  if (!$isRangeSelection(selection)) {\n    return false;\n  }\n\n  const elementNodesInSelection = getElementNodesInSelection(selection);\n\n  let totalDepth = 0;\n\n  for (const elementNode of elementNodesInSelection) {\n    if ($isListNode(elementNode)) {\n      totalDepth = Math.max($getListDepth(elementNode) + 1, totalDepth);\n    } else if ($isListItemNode(elementNode)) {\n      const parent = elementNode.getParent();\n      if (!$isListNode(parent)) {\n        throw new Error(\n          \"ListMaxIndentLevelPlugin: A ListItemNode must have a ListNode for a parent.\"\n        );\n      }\n\n      totalDepth = Math.max($getListDepth(parent) + 1, totalDepth);\n    }\n  }\n\n  return totalDepth <= maxDepth;\n}\n\nexport default function ListMaxIndentLevelPlugin({ maxDepth }) {\n  const [editor] = useLexicalComposerContext();\n\n  useEffect(() => {\n    return editor.registerCommand(\n      INDENT_CONTENT_COMMAND,\n      () => !isIndentPermitted(maxDepth ?? 7),\n      COMMAND_PRIORITY_HIGH\n    );\n  }, [editor, maxDepth]);\n\n  return null;\n}\n"
  },
  {
    "path": "src/components/LexicalEditor/RichEditor.jsx",
    "content": "import { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\nimport { AutoFocusPlugin } from \"@lexical/react/LexicalAutoFocusPlugin\";\nimport { LinkPlugin } from \"@lexical/react/LexicalLinkPlugin\";\nimport { ListPlugin } from \"@lexical/react/LexicalListPlugin\";\nimport { MarkdownShortcutPlugin } from \"@lexical/react/LexicalMarkdownShortcutPlugin\";\nimport { ClearEditorPlugin } from \"@lexical/react/LexicalClearEditorPlugin\";\nimport { TRANSFORMERS } from \"@lexical/markdown\";\nimport LexicalErrorBoundary from \"@lexical/react/LexicalErrorBoundary\";\nimport ToolbarPlugin from \"./ToolbarPlugin\";\nimport ListMaxIndentLevelPlugin from \"./ListMaxIndentLevelPlugin\";\nimport CodeHighlightPlugin from \"./CodeHighlightPlugin\";\nimport AutoLinkPlugin from \"./AutoLinkPlugin\";\nimport \"./styles/index.css\";\n\nfunction Placeholder({ text }) {\n  return <div className=\"editor-placeholder\">{text || \"\"}</div>;\n}\n\nexport default function RichEditor({ theme, placeholder }) {\n  return (\n    <div className=\"editor-container\">\n      <ToolbarPlugin theme={theme} />\n      <div className=\"editor-inner\">\n        <RichTextPlugin\n          contentEditable={<ContentEditable className=\"editor-input\" />}\n          placeholder={<Placeholder text={placeholder} />}\n          ErrorBoundary={LexicalErrorBoundary}\n        />\n        <HistoryPlugin />\n        <AutoFocusPlugin />\n        <CodeHighlightPlugin />\n        <ListPlugin />\n        <LinkPlugin />\n        <AutoLinkPlugin />\n        <ListMaxIndentLevelPlugin maxDepth={7} />\n        <MarkdownShortcutPlugin transformers={TRANSFORMERS} />\n        <ClearEditorPlugin />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/LexicalEditor/ToolbarPlugin.jsx",
    "content": "/**\n * See https://codesandbox.io/p/sandbox/vigilant-kate-5tncvy?file=%2Fsrc%2Fplugins%2FToolbarPlugin.js\n */\n\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n  CAN_REDO_COMMAND,\n  CAN_UNDO_COMMAND,\n  REDO_COMMAND,\n  UNDO_COMMAND,\n  SELECTION_CHANGE_COMMAND,\n  FORMAT_TEXT_COMMAND,\n  FORMAT_ELEMENT_COMMAND,\n  $getSelection,\n  $isRangeSelection,\n  $createParagraphNode,\n  $getNodeByKey,\n} from \"lexical\";\nimport { $isLinkNode, TOGGLE_LINK_COMMAND } from \"@lexical/link\";\nimport {\n  $isParentElementRTL,\n  $wrapNodes,\n  $isAtNodeEnd,\n} from \"@lexical/selection\";\nimport { $getNearestNodeOfType, mergeRegister } from \"@lexical/utils\";\nimport {\n  INSERT_ORDERED_LIST_COMMAND,\n  INSERT_UNORDERED_LIST_COMMAND,\n  REMOVE_LIST_COMMAND,\n  $isListNode,\n  ListNode,\n} from \"@lexical/list\";\nimport { createPortal } from \"react-dom\";\nimport {\n  $createHeadingNode,\n  $createQuoteNode,\n  $isHeadingNode,\n} from \"@lexical/rich-text\";\nimport {\n  $createCodeNode,\n  $isCodeNode,\n  getDefaultCodeLanguage,\n  getCodeLanguages,\n} from \"@lexical/code\";\nimport { Dropdown } from \"@douyinfe/semi-ui\";\nimport \"./styles/index.css\";\n\nconst LowPriority = 1;\n\nconst blockTypeToIcon = {\n  code: \"bi-code-slash\",\n  h1: \"bi-type-h1\",\n  h2: \"bi-type-h2\",\n  ol: \"bi-list-ol\",\n  paragraph: \"bi-text-paragraph\",\n  quote: \"bi-chat-square-quote\",\n  ul: \"bi-list-ul\",\n};\n\nconst blockTypeToBlockName = {\n  paragraph: \"Paragraph\",\n  h1: \"Large Heading\",\n  h2: \"Small Heading\",\n  ul: \"Bulleted List\",\n  ol: \"Numbered List\",\n  code: \"Code Block\",\n  quote: \"Quote\",\n};\n\nfunction Divider() {\n  return <div className=\"divider\" />;\n}\n\nfunction positionEditorElement(editor, rect) {\n  if (rect === null) {\n    editor.style.opacity = \"0\";\n    editor.style.top = \"-1000px\";\n    editor.style.left = \"-1000px\";\n  } else {\n    editor.style.opacity = \"1\";\n    editor.style.top = `${rect.top + rect.height + window.pageYOffset + 10}px`;\n    editor.style.left = `${\n      rect.left + window.pageXOffset - editor.offsetWidth / 2 + rect.width / 2\n    }px`;\n  }\n}\n\nfunction FloatingLinkEditor({ editor }) {\n  const editorRef = useRef(null);\n  const inputRef = useRef(null);\n  const [linkUrl, setLinkUrl] = useState(\"\");\n  const [isEditMode, setEditMode] = useState(false);\n  const [lastSelection, setLastSelection] = useState(null);\n\n  const updateLinkEditor = useCallback(() => {\n    const selection = $getSelection();\n    if ($isRangeSelection(selection)) {\n      const node = getSelectedNode(selection);\n      const parent = node.getParent();\n      if ($isLinkNode(parent)) {\n        setLinkUrl(parent.getURL());\n      } else if ($isLinkNode(node)) {\n        setLinkUrl(node.getURL());\n      } else {\n        setLinkUrl(\"\");\n      }\n    }\n    const editorElem = editorRef.current;\n    const nativeSelection = window.getSelection();\n    const activeElement = document.activeElement;\n\n    if (editorElem === null) {\n      return;\n    }\n\n    const rootElement = editor.getRootElement();\n    if (\n      selection !== null &&\n      !nativeSelection.isCollapsed &&\n      rootElement !== null &&\n      rootElement.contains(nativeSelection.anchorNode)\n    ) {\n      const domRange = nativeSelection.getRangeAt(0);\n      let rect;\n      if (nativeSelection.anchorNode === rootElement) {\n        let inner = rootElement;\n        while (inner.firstElementChild != null) {\n          inner = inner.firstElementChild;\n        }\n        rect = inner.getBoundingClientRect();\n      } else {\n        rect = domRange.getBoundingClientRect();\n      }\n\n      positionEditorElement(editorElem, rect);\n      setLastSelection(selection);\n    } else if (!activeElement || activeElement.className !== \"link-input\") {\n      positionEditorElement(editorElem, null);\n      setLastSelection(null);\n      setEditMode(false);\n      setLinkUrl(\"\");\n    }\n\n    return true;\n  }, [editor]);\n\n  useEffect(() => {\n    return mergeRegister(\n      editor.registerUpdateListener(({ editorState }) => {\n        editorState.read(() => {\n          updateLinkEditor();\n        });\n      }),\n\n      editor.registerCommand(\n        SELECTION_CHANGE_COMMAND,\n        () => {\n          updateLinkEditor();\n          return true;\n        },\n        LowPriority\n      )\n    );\n  }, [editor, updateLinkEditor]);\n\n  useEffect(() => {\n    editor.getEditorState().read(() => {\n      updateLinkEditor();\n    });\n  }, [editor, updateLinkEditor]);\n\n  useEffect(() => {\n    if (isEditMode && inputRef.current) {\n      inputRef.current.focus();\n    }\n  }, [isEditMode]);\n\n  return (\n    <div ref={editorRef} className=\"link-editor\">\n      {isEditMode ? (\n        <input\n          ref={inputRef}\n          className=\"link-input\"\n          value={linkUrl}\n          onChange={(event) => {\n            setLinkUrl(event.target.value);\n          }}\n          onKeyDown={(event) => {\n            if (event.key === \"Enter\") {\n              event.preventDefault();\n              if (lastSelection !== null) {\n                if (linkUrl !== \"\") {\n                  editor.dispatchCommand(TOGGLE_LINK_COMMAND, linkUrl);\n                }\n                setEditMode(false);\n              }\n            } else if (event.key === \"Escape\") {\n              event.preventDefault();\n              setEditMode(false);\n            }\n          }}\n        />\n      ) : (\n        <>\n          <div className=\"link-input\">\n            <a href={linkUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n              {linkUrl}\n            </a>\n          </div>\n        </>\n      )}\n    </div>\n  );\n}\n\nfunction Select({ onChange, className, options, value }) {\n  return (\n    <select className={className} onChange={onChange} value={value}>\n      <option hidden={true} value=\"\" />\n      {options.map((option) => (\n        <option className=\"option\" key={option} value={option}>\n          {option}\n        </option>\n      ))}\n    </select>\n  );\n}\n\nfunction getSelectedNode(selection) {\n  const anchor = selection.anchor;\n  const focus = selection.focus;\n  const anchorNode = selection.anchor.getNode();\n  const focusNode = selection.focus.getNode();\n  if (anchorNode === focusNode) {\n    return anchorNode;\n  }\n  const isBackward = selection.isBackward();\n  if (isBackward) {\n    return $isAtNodeEnd(focus) ? anchorNode : focusNode;\n  } else {\n    return $isAtNodeEnd(anchor) ? focusNode : anchorNode;\n  }\n}\n\nfunction BlockOptionsDropdownList({ editor, blockType }) {\n  const formatParagraph = () => {\n    if (blockType !== \"paragraph\") {\n      editor.update(() => {\n        const selection = $getSelection();\n        if ($isRangeSelection(selection)) {\n          $wrapNodes(selection, () => $createParagraphNode());\n        }\n      });\n    }\n  };\n\n  const formatLargeHeading = () => {\n    if (blockType !== \"h1\") {\n      editor.update(() => {\n        const selection = $getSelection();\n        if ($isRangeSelection(selection)) {\n          $wrapNodes(selection, () => $createHeadingNode(\"h1\"));\n        }\n      });\n    }\n  };\n\n  const formatSmallHeading = () => {\n    if (blockType !== \"h2\") {\n      editor.update(() => {\n        const selection = $getSelection();\n        if ($isRangeSelection(selection)) {\n          $wrapNodes(selection, () => $createHeadingNode(\"h2\"));\n        }\n      });\n    }\n  };\n\n  const formatBulletList = () => {\n    if (blockType !== \"ul\") {\n      editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND);\n    } else {\n      editor.dispatchCommand(REMOVE_LIST_COMMAND);\n    }\n  };\n\n  const formatNumberedList = () => {\n    if (blockType !== \"ol\") {\n      editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND);\n    } else {\n      editor.dispatchCommand(REMOVE_LIST_COMMAND);\n    }\n  };\n\n  const formatQuote = () => {\n    if (blockType !== \"quote\") {\n      editor.update(() => {\n        const selection = $getSelection();\n        if ($isRangeSelection(selection)) {\n          $wrapNodes(selection, () => $createQuoteNode());\n        }\n      });\n    }\n  };\n\n  const formatCode = () => {\n    if (blockType !== \"code\") {\n      editor.update(() => {\n        const selection = $getSelection();\n        if ($isRangeSelection(selection)) {\n          $wrapNodes(selection, () => $createCodeNode());\n        }\n      });\n    }\n  };\n\n  return (\n    <Dropdown\n      trigger=\"click\"\n      clickToHide\n      render={\n        <Dropdown.Menu>\n          <Dropdown.Item\n            onClick={formatParagraph}\n            icon={<i className={`bi ${blockTypeToIcon.paragraph}`} />}\n          >\n            Paragraph\n          </Dropdown.Item>\n          <Dropdown.Item\n            onClick={formatLargeHeading}\n            icon={<i className={`bi ${blockTypeToIcon.h1}`} />}\n          >\n            Large Heading\n          </Dropdown.Item>\n          <Dropdown.Item\n            onClick={formatSmallHeading}\n            icon={<i className={`bi ${blockTypeToIcon.h2}`} />}\n          >\n            Small Heading\n          </Dropdown.Item>\n          <Dropdown.Item\n            onClick={formatBulletList}\n            icon={<i className={`bi ${blockTypeToIcon.ul}`} />}\n          >\n            Bullet List\n          </Dropdown.Item>\n          <Dropdown.Item\n            onClick={formatNumberedList}\n            icon={<i className={`bi ${blockTypeToIcon.ol}`} />}\n          >\n            Numbered List\n          </Dropdown.Item>\n          <Dropdown.Item\n            onClick={formatQuote}\n            icon={<i className={`bi ${blockTypeToIcon.quote}`} />}\n          >\n            Quote\n          </Dropdown.Item>\n          <Dropdown.Item\n            onClick={formatCode}\n            icon={<i className={`bi ${blockTypeToIcon.code}`} />}\n          >\n            Code Block\n          </Dropdown.Item>\n        </Dropdown.Menu>\n      }\n    >\n      <button\n        className=\"flex mx-2 justify-center items-center\"\n        aria-label=\"Formatting Options\"\n      >\n        <i className={`bi ${blockTypeToIcon[blockType]} me-3`} />\n        <span className=\"me-3 text-sm\">{blockTypeToBlockName[blockType]}</span>\n        <i className=\"bi bi-chevron-down\" />\n      </button>\n    </Dropdown>\n  );\n}\n\nexport default function ToolbarPlugin() {\n  const [editor] = useLexicalComposerContext();\n  const toolbarRef = useRef(null);\n  const [canUndo, setCanUndo] = useState(false);\n  const [canRedo, setCanRedo] = useState(false);\n  const [blockType, setBlockType] = useState(\"paragraph\");\n  const [selectedElementKey, setSelectedElementKey] = useState(null);\n  const [codeLanguage, setCodeLanguage] = useState(\"\");\n  const [, setIsRTL] = useState(false);\n  const [isLink, setIsLink] = useState(false);\n  const [isBold, setIsBold] = useState(false);\n  const [isItalic, setIsItalic] = useState(false);\n  const [isUnderline, setIsUnderline] = useState(false);\n  const [isStrikethrough, setIsStrikethrough] = useState(false);\n  const [isCode, setIsCode] = useState(false);\n\n  const updateToolbar = useCallback(() => {\n    const selection = $getSelection();\n    if ($isRangeSelection(selection)) {\n      const anchorNode = selection.anchor.getNode();\n      const element =\n        anchorNode.getKey() === \"root\"\n          ? anchorNode\n          : anchorNode.getTopLevelElementOrThrow();\n      const elementKey = element.getKey();\n      const elementDOM = editor.getElementByKey(elementKey);\n      if (elementDOM !== null) {\n        setSelectedElementKey(elementKey);\n        if ($isListNode(element)) {\n          const parentList = $getNearestNodeOfType(anchorNode, ListNode);\n          const type = parentList ? parentList.getTag() : element.getTag();\n          setBlockType(type);\n        } else {\n          const type = $isHeadingNode(element)\n            ? element.getTag()\n            : element.getType();\n          setBlockType(type);\n          if ($isCodeNode(element)) {\n            setCodeLanguage(element.getLanguage() || getDefaultCodeLanguage());\n          }\n        }\n      }\n\n      setIsBold(selection.hasFormat(\"bold\"));\n      setIsItalic(selection.hasFormat(\"italic\"));\n      setIsUnderline(selection.hasFormat(\"underline\"));\n      setIsStrikethrough(selection.hasFormat(\"strikethrough\"));\n      setIsCode(selection.hasFormat(\"code\"));\n      setIsRTL($isParentElementRTL(selection));\n\n      const node = getSelectedNode(selection);\n      const parent = node.getParent();\n      if ($isLinkNode(parent) || $isLinkNode(node)) {\n        setIsLink(true);\n      } else {\n        setIsLink(false);\n      }\n    }\n  }, [editor]);\n\n  useEffect(() => {\n    return mergeRegister(\n      editor.registerUpdateListener(({ editorState }) => {\n        editorState.read(() => {\n          updateToolbar();\n        });\n      }),\n      editor.registerCommand(\n        SELECTION_CHANGE_COMMAND,\n        () => {\n          updateToolbar();\n          return false;\n        },\n        LowPriority\n      ),\n      editor.registerCommand(\n        CAN_UNDO_COMMAND,\n        (payload) => {\n          setCanUndo(payload);\n          return false;\n        },\n        LowPriority\n      ),\n      editor.registerCommand(\n        CAN_REDO_COMMAND,\n        (payload) => {\n          setCanRedo(payload);\n          return false;\n        },\n        LowPriority\n      )\n    );\n  }, [editor, updateToolbar]);\n\n  const codeLanguges = useMemo(() => getCodeLanguages(), []);\n  const onCodeLanguageSelect = useCallback(\n    (e) => {\n      editor.update(() => {\n        if (selectedElementKey !== null) {\n          const node = $getNodeByKey(selectedElementKey);\n          if ($isCodeNode(node)) {\n            node.setLanguage(e.target.value);\n          }\n        }\n      });\n    },\n    [editor, selectedElementKey]\n  );\n\n  const insertLink = useCallback(() => {\n    if (!isLink) {\n      editor.dispatchCommand(TOGGLE_LINK_COMMAND, \"https://\");\n    } else {\n      editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);\n    }\n  }, [editor, isLink]);\n\n  return (\n    <div className=\"toolbar\" ref={toolbarRef}>\n      <button\n        disabled={!canUndo}\n        onClick={() => editor.dispatchCommand(UNDO_COMMAND)}\n        className=\"toolbar-item spaced\"\n        aria-label=\"Undo\"\n      >\n        <i\n          className={`bi bi-arrow-counterclockwise ${\n            canUndo ? \"\" : \"opacity-30\"\n          }`}\n        />\n      </button>\n      <button\n        disabled={!canRedo}\n        onClick={() => editor.dispatchCommand(REDO_COMMAND)}\n        className=\"toolbar-item\"\n        aria-label=\"Redo\"\n      >\n        <i className={`bi bi-arrow-clockwise ${canRedo ? \"\" : \"opacity-30\"}`} />\n      </button>\n      <Divider />\n      <BlockOptionsDropdownList editor={editor} blockType={blockType} />\n      <Divider />\n      {blockType === \"code\" ? (\n        <div className=\"flex items-center\">\n          <Select\n            className=\"toolbar-item code-language\"\n            onChange={onCodeLanguageSelect}\n            options={codeLanguges}\n            value={codeLanguage}\n          />\n          <i className=\"bi bi-chevron-down\" />\n        </div>\n      ) : (\n        <>\n          <button\n            onClick={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"bold\")}\n            className={\"toolbar-item spaced \" + (isBold ? \"active\" : \"\")}\n            aria-label=\"Format Bold\"\n          >\n            <i className=\"bi bi-type-bold\" />\n          </button>\n          <button\n            onClick={() =>\n              editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"italic\")\n            }\n            className={\"toolbar-item spaced \" + (isItalic ? \"active\" : \"\")}\n            aria-label=\"Format Italics\"\n          >\n            <i className=\"bi bi-type-italic\" />\n          </button>\n          <button\n            onClick={() =>\n              editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"underline\")\n            }\n            className={\"toolbar-item spaced \" + (isUnderline ? \"active\" : \"\")}\n            aria-label=\"Format Underline\"\n          >\n            <i className=\"bi bi-type-underline\" />\n          </button>\n          <button\n            onClick={() =>\n              editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"strikethrough\")\n            }\n            className={\n              \"toolbar-item spaced \" + (isStrikethrough ? \"active\" : \"\")\n            }\n            aria-label=\"Format Strikethrough\"\n          >\n            <i className=\"bi bi-type-strikethrough\" />\n          </button>\n          <button\n            onClick={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"code\")}\n            className={\"toolbar-item spaced \" + (isCode ? \"active\" : \"\")}\n            aria-label=\"Insert Code\"\n          >\n            <i className=\"bi bi-code-slash\" />\n          </button>\n          <button\n            onClick={insertLink}\n            className={\"toolbar-item spaced \" + (isLink ? \"active\" : \"\")}\n            aria-label=\"Insert Link\"\n          >\n            <i className=\"bi bi-link\" />\n          </button>\n          {isLink &&\n            createPortal(\n              <FloatingLinkEditor editor={editor} />,\n              document.body\n            )}\n          <Divider />\n          <button\n            onClick={() =>\n              editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, \"left\")\n            }\n            className=\"toolbar-item spaced\"\n            aria-label=\"Left Align\"\n          >\n            <i className=\"bi bi-text-left\" />\n          </button>\n          <button\n            onClick={() =>\n              editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, \"center\")\n            }\n            className=\"toolbar-item spaced\"\n            aria-label=\"Center Align\"\n          >\n            <i className=\"bi bi-text-center\" />\n          </button>\n          <button\n            onClick={() => {\n              editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, \"right\");\n            }}\n            className=\"toolbar-item spaced\"\n            aria-label=\"Right Align\"\n          >\n            <i className=\"bi bi-text-right\" />\n          </button>\n          <button\n            onClick={() => {\n              editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, \"justify\");\n            }}\n            className=\"toolbar-item\"\n            aria-label=\"Justify Align\"\n          >\n            <i className=\"bi bi-justify\" />\n          </button>\n        </>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/LexicalEditor/styles/index.css",
    "content": "/* See https://codesandbox.io/p/sandbox/vigilant-kate-5tncvy?file=%2Fsrc%2Fstyles.css */\n\n.ltr {\n  text-align: left;\n}\n\n.rtl {\n  text-align: right;\n}\n\n.editor-container {\n  margin: 16px auto 16px auto;\n  border-radius: 6px;\n  color: var(--semi-color-text-1);\n  background-color: rgba(var(--semi-grey-1), 1);\n  position: relative;\n  line-height: 20px;\n  font-weight: 400;\n  text-align: left;\n}\n\n.editor-inner {\n  background-color: rgba(var(--semi-grey-1), 1);\n  position: relative;\n  border-radius: 6px;\n}\n\n.editor-input {\n  min-height: 160px;\n  resize: none;\n  font-size: 15px;\n  position: relative;\n  tab-size: 1;\n  outline: 0;\n  padding: 15px 10px;\n}\n\n.editor-placeholder {\n  color: #999;\n  position: absolute;\n  text-overflow: ellipsis;\n  top: 15px;\n  left: 10px;\n  font-size: 15px;\n  user-select: none;\n  display: inline-block;\n  pointer-events: none;\n}\n\n.editor-text-bold {\n  font-weight: bold;\n}\n\n.editor-text-italic {\n  font-style: italic;\n}\n\n.editor-text-underline {\n  text-decoration: underline;\n}\n\n.editor-text-strikethrough {\n  text-decoration: line-through;\n}\n\n.editor-text-underlineStrikethrough {\n  text-decoration: underline line-through;\n}\n\n.editor-text-code {\n  background-color: rgba(var(--semi-grey-2), 1);\n  padding: 1px 0.25rem;\n  font-family: Menlo, Consolas, Monaco, monospace;\n  font-size: 94%;\n}\n\n.editor-link {\n  color: rgb(33, 111, 219);\n  text-decoration: none;\n}\n\n.editor-code {\n  background-color: rgba(var(--semi-grey-0), 1);\n  font-family: Menlo, Consolas, Monaco, monospace;\n  display: block;\n  padding: 8px 8px 8px 52px;\n  line-height: 1.53;\n  font-size: 13px;\n  margin: 0;\n  margin-top: 8px;\n  margin-bottom: 8px;\n  tab-size: 2;\n  overflow-x: auto;\n  position: relative;\n}\n\n.editor-code:before {\n  content: attr(data-gutter);\n  position: absolute;\n  background-color: rgba(var(--semi-grey-0), 1);\n  left: 0;\n  top: 0;\n  border-right: 1px solid rgba(var(--semi-grey-3), 1);\n  padding: 8px;\n  color: #777;\n  white-space: pre-wrap;\n  text-align: right;\n  min-width: 25px;\n}\n\n.editor-code:after {\n  content: attr(data-highlight-language);\n  top: 0;\n  right: 3px;\n  padding: 3px;\n  font-size: 10px;\n  text-transform: uppercase;\n  position: absolute;\n  color: rgba(var(--semi-text-1), 1);\n}\n\n.editor-tokenComment {\n  color: slategray;\n}\n\n.editor-tokenPunctuation {\n  color: #999;\n}\n\n.editor-tokenProperty {\n  color: #905;\n}\n\n.editor-tokenSelector {\n  color: #690;\n}\n\n.editor-tokenOperator {\n  color: #9a6e3a;\n}\n\n.editor-tokenAttr {\n  color: #07a;\n}\n\n.editor-tokenVariable {\n  color: #e90;\n}\n\n.editor-tokenFunction {\n  color: #dd4a68;\n}\n\n.editor-paragraph {\n  margin: 0;\n  margin-bottom: 8px;\n  position: relative;\n}\n\n.editor-paragraph:last-child {\n  margin-bottom: 0;\n}\n\n.editor-heading-h1 {\n  font-size: 24px;\n  margin: 0;\n  margin-bottom: 12px;\n  padding: 0;\n}\n\n.editor-heading-h2 {\n  font-size: 16px;\n  margin: 0;\n  margin-top: 10px;\n  padding: 0;\n}\n\n.editor-quote {\n  margin: 0;\n  margin-left: 20px;\n  font-size: 15px;\n  color: rgb(101, 103, 107);\n  border-left-color: rgb(206, 208, 212);\n  border-left-width: 4px;\n  border-left-style: solid;\n  padding-left: 16px;\n}\n\n.editor-list-ol {\n  padding: 0;\n  margin: 0;\n  margin-left: 16px;\n  list-style-type: decimal;\n}\n\n.editor-list-ul {\n  padding: 0;\n  margin: 0;\n  margin-left: 16px;\n  list-style-type: circle;\n}\n\n.editor-listitem {\n  margin: 8px 32px 8px 32px;\n}\n\n.editor-nested-listitem {\n  list-style-type: none;\n}\n\npre::-webkit-scrollbar {\n  background: transparent;\n  width: 10px;\n}\n\npre::-webkit-scrollbar-thumb {\n  background: #999;\n}\n\n.toolbar {\n  display: flex;\n  flex-wrap: wrap;\n  margin-bottom: 1px;\n  background-color: rgba(var(--semi-grey-1), 1);\n  padding: 4px;\n  border-top-left-radius: 10px;\n  border-top-right-radius: 10px;\n  border-bottom: rgba(var(--semi-grey-2), 1) solid 2px;\n  vertical-align: middle;\n}\n\n.toolbar button.toolbar-item {\n  border: 0;\n  display: flex;\n  border-radius: 6px;\n  padding: 8px;\n  cursor: pointer;\n  vertical-align: middle;\n  fill: currentColor;\n}\n\n.toolbar button.toolbar-item:disabled {\n  cursor: not-allowed;\n}\n\n.toolbar button.toolbar-item.spaced {\n  margin-right: 2px;\n}\n\n.toolbar button.toolbar-item i.format {\n  background-size: contain;\n  display: inline-block;\n  height: 18px;\n  width: 18px;\n  margin-top: 2px;\n  vertical-align: -0.25em;\n  display: flex;\n  opacity: 1;\n  fill: currentColor;\n}\n\n.toolbar button.toolbar-item:disabled i.format {\n  opacity: 0.4;\n}\n\n.toolbar button.toolbar-item.active {\n  background-color: rgba(var(--semi-grey-2), 1);\n}\n\n.toolbar button.toolbar-item.active i {\n  opacity: 1;\n}\n\n.toolbar .toolbar-item:hover:not([disabled]) {\n  background-color: rgba(var(--semi-grey-2), 1);\n}\n\n.toolbar .divider {\n  width: 2px;\n  background-color: rgba(var(--semi-grey-2), 1);\n  margin: 4px 4px;\n}\n\n.toolbar select.toolbar-item {\n  border-radius: 6px;\n  padding: 8px;\n  vertical-align: middle;\n  appearance: none;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  font-size: 14px;\n  background-color: rgba(var(--semi-grey-1), 1);\n  text-overflow: ellipsis;\n  outline: none;\n}\n\n.toolbar select.code-language {\n  text-transform: capitalize;\n  width: 130px;\n}\n\n.toolbar .toolbar-item .text {\n  line-height: 20px;\n  width: 200px;\n  vertical-align: middle;\n  font-size: 14px;\n  color: rgba(var(--semi-text-1), 1);\n  text-overflow: ellipsis;\n  width: 70px;\n  overflow: hidden;\n  height: 20px;\n  text-align: left;\n}\n\n.toolbar .toolbar-item .icon {\n  width: 20px;\n  height: 20px;\n  user-select: none;\n  margin-right: 8px;\n  line-height: 16px;\n  background-size: contain;\n}\n\n.link-editor {\n  position: absolute;\n  z-index: 100;\n  top: -10000px;\n  left: -10000px;\n  margin-top: -6px;\n  max-width: 300px;\n  width: 100%;\n  opacity: 0;\n  background-color: rgba(var(--semi-grey-1), 1);\n  box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.3);\n  border-radius: 6px;\n  transition: opacity 0.5s;\n}\n\n.link-editor .link-input {\n  display: block;\n  width: calc(100% - 24px);\n  box-sizing: border-box;\n  margin: 8px 12px;\n  padding: 8px 12px;\n  border-radius: 6px;\n  background-color: rgba(var(--semi-grey-2), 1);\n  font-size: 15px;\n  color: var(--semi-color-text-1);\n  border: 0;\n  outline: 0;\n  position: relative;\n  font-family: inherit;\n}\n\n.link-editor .link-input a {\n  color: rgb(33, 111, 219);\n  text-decoration: none;\n  display: block;\n  white-space: nowrap;\n  overflow: hidden;\n  margin-right: 30px;\n  text-overflow: ellipsis;\n}\n\n.link-editor .link-input a:hover {\n  text-decoration: underline;\n}\n\n.link-editor .button {\n  width: 20px;\n  height: 20px;\n  display: inline-block;\n  padding: 6px;\n  border-radius: 8px;\n  cursor: pointer;\n  margin: 0 2px;\n}\n\n.link-editor .button.hovered {\n  width: 20px;\n  height: 20px;\n  display: inline-block;\n  background-color: #eee;\n}\n\n.link-editor .button i,\n.actions i {\n  background-size: contain;\n  display: inline-block;\n  height: 20px;\n  width: 20px;\n  vertical-align: -0.25em;\n}"
  },
  {
    "path": "src/components/Navbar.jsx",
    "content": "import { useState } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport logo from \"../assets/logo_light_160.png\";\nimport { SideSheet } from \"@douyinfe/semi-ui\";\nimport { IconMenu } from \"@douyinfe/semi-icons\";\nimport { socials } from \"../data/socials\";\n\nexport default function Navbar() {\n  const [openMenu, setOpenMenu] = useState(false);\n\n  return (\n    <>\n      <div className=\"py-4 px-12 sm:px-4 flex justify-between items-center\">\n        <div className=\"flex items-center justify-between w-full\">\n          <Link to=\"/\">\n            <img src={logo} alt=\"logo\" className=\"h-[48px] sm:h-[32px]\" />\n          </Link>\n          <div className=\"md:hidden flex gap-12\">\n            <Link\n              className=\"text-lg font-semibold hover:text-sky-800 transition-colors duration-300\"\n              onClick={() =>\n                document\n                  .getElementById(\"features\")\n                  .scrollIntoView({ behavior: \"smooth\" })\n              }\n            >\n              Features\n            </Link>\n            <Link\n              to=\"/editor\"\n              className=\"text-lg font-semibold hover:text-sky-800 transition-colors duration-300\"\n            >\n              Editor\n            </Link>\n            <Link\n              to=\"/templates\"\n              className=\"text-lg font-semibold hover:text-sky-800 transition-colors duration-300\"\n            >\n              Templates\n            </Link>\n            <Link\n              to={socials.docs}\n              className=\"text-lg font-semibold hover:text-sky-800 transition-colors duration-300\"\n            >\n              Docs\n            </Link>\n          </div>\n          <div className=\"md:hidden block space-x-3 ms-12\">\n            <a\n              title=\"Jump to Github\"\n              className=\"px-2 py-2 hover:opacity-60 transition-all duration-300 rounded-full text-2xl\"\n              href={socials.github}\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              <i className=\"opacity-70 bi bi-github\" />\n            </a>\n            <a\n              title=\"Follow us on X\"\n              className=\"px-2 py-2 hover:opacity-60 transition-all duration-300 rounded-full text-2xl\"\n              href={socials.twitter}\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              <i className=\"opacity-70 bi bi-twitter-x\" />\n            </a>\n            <a\n              title=\"Join the community on Discord\"\n              className=\"px-2 py-2 hover:opacity-60 transition-all duration-300 rounded-full text-2xl\"\n              href={socials.discord}\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              <i className=\"opacity-70 bi bi-discord\" />\n            </a>\n          </div>\n        </div>\n        <button\n          onClick={() => setOpenMenu((prev) => !prev)}\n          className=\"hidden md:inline-block h-[24px]\"\n        >\n          <IconMenu size=\"extra-large\" />\n        </button>\n      </div>\n      <hr />\n      <SideSheet\n        title={\n          <img src={logo} alt=\"logo\" className=\"sm:h-[32px] md:h-[42px]\" />\n        }\n        visible={openMenu}\n        onCancel={() => setOpenMenu(false)}\n        width={window.innerWidth}\n      >\n        <Link\n          className=\"hover:bg-zinc-100 block p-3 text-base font-semibold\"\n          onClick={() => {\n            document\n              .getElementById(\"features\")\n              .scrollIntoView({ behavior: \"smooth\" });\n            setOpenMenu(false);\n          }}\n        >\n          Features\n        </Link>\n        <hr />\n        <Link\n          to=\"/editor\"\n          className=\"hover:bg-zinc-100 block p-3 text-base font-semibold\"\n        >\n          Editor\n        </Link>\n        <hr />\n        <Link\n          to=\"/templates\"\n          className=\"hover:bg-zinc-100 block p-3 text-base font-semibold\"\n        >\n          Templates\n        </Link>\n        <hr />\n        <Link\n          to={socials.docs}\n          className=\"hover:bg-zinc-100 block p-3 text-base font-semibold\"\n        >\n          Docs\n        </Link>\n      </SideSheet>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/SimpleCanvas.jsx",
    "content": "import { useEffect, useState, useRef } from \"react\";\nimport {\n  Cardinality,\n  tableColorStripHeight,\n  tableFieldHeight,\n  tableHeaderHeight,\n  tableWidth,\n} from \"../data/constants\";\nimport { calcPath } from \"../utils/calcPath\";\n\nfunction Table({ table, grab }) {\n  const [isHovered, setIsHovered] = useState(false);\n  const [hoveredField, setHoveredField] = useState(-1);\n  const height =\n    table.fields.length * tableFieldHeight +\n    tableHeaderHeight +\n    tableColorStripHeight;\n\n  return (\n    <foreignObject\n      key={table.name}\n      x={table.x}\n      y={table.y}\n      width={tableWidth}\n      height={height}\n      className=\"drop-shadow-lg rounded-md cursor-move\"\n      onPointerDown={(e) => {\n        // Required for onPointerLeave to trigger when a touch pointer leaves\n        // https://stackoverflow.com/a/70976017/1137077\n        e.target.releasePointerCapture(e.pointerId);\n\n        if (!e.isPrimary) return;\n\n        grab(e);\n      }}\n      onPointerEnter={(e) => e.isPrimary && setIsHovered(true)}\n      onPointerLeave={(e) => e.isPrimary && setIsHovered(false)}\n    >\n      <div\n        className={`border-2 ${\n          isHovered ? \"border-dashed border-blue-500\" : \"border-zinc-300\"\n        } select-none rounded-lg w-full bg-zinc-100 text-zinc-800`}\n      >\n        <div\n          className={`h-[10px] w-full rounded-t-md`}\n          style={{ backgroundColor: table.color }}\n        />\n        <div className=\"font-bold h-[40px] flex justify-between items-center border-b border-zinc-400 bg-zinc-200 px-3\">\n          {table.name}\n        </div>\n        {table.fields.map((e, i) => (\n          <div\n            key={i}\n            className={`${\n              i === table.fields.length - 1 ? \"\" : \"border-b border-gray-400\"\n            } h-[36px] px-2 py-1 flex justify-between`}\n            onPointerEnter={(e) => e.isPrimary && setHoveredField(i)}\n            onPointerLeave={(e) => e.isPrimary && setHoveredField(-1)}\n            onPointerDown={(e) => {\n              // Required for onPointerLeave to trigger when a touch pointer leaves\n              // https://stackoverflow.com/a/70976017/1137077\n              e.target.releasePointerCapture(e.pointerId);\n            }}\n          >\n            <div className={hoveredField === i ? \"text-zinc-500\" : \"\"}>\n              <button\n                className={`w-[9px] h-[9px] bg-[#2f68adcc] rounded-full me-2`}\n              />\n              {e.name}\n            </div>\n            <div className=\"text-zinc-400\">{e.type}</div>\n          </div>\n        ))}\n      </div>\n    </foreignObject>\n  );\n}\n\nfunction Relationship({ relationship, tables }) {\n  const pathRef = useRef();\n  let start = { x: 0, y: 0 };\n  let end = { x: 0, y: 0 };\n\n  let cardinalityStart = \"1\";\n  let cardinalityEnd = \"1\";\n\n  switch (relationship.cardinality) {\n    case Cardinality.MANY_TO_ONE:\n      cardinalityStart = \"n\";\n      cardinalityEnd = \"1\";\n      break;\n    case Cardinality.ONE_TO_MANY:\n      cardinalityStart = \"1\";\n      cardinalityEnd = \"n\";\n      break;\n    case Cardinality.ONE_TO_ONE:\n      cardinalityStart = \"1\";\n      cardinalityEnd = \"1\";\n      break;\n    default:\n      break;\n  }\n\n  const length = 32;\n\n  const [refAquired, setRefAquired] = useState(false);\n  useEffect(() => {\n    setRefAquired(true);\n  }, []);\n\n  if (refAquired) {\n    const pathLength = pathRef.current.getTotalLength();\n    const point1 = pathRef.current.getPointAtLength(length);\n    start = { x: point1.x, y: point1.y };\n    const point2 = pathRef.current.getPointAtLength(pathLength - length);\n    end = { x: point2.x, y: point2.y };\n  }\n\n  return (\n    <g className=\"select-none\">\n      <path\n        ref={pathRef}\n        d={calcPath({\n          startFieldIndex: relationship.startFieldId,\n          endFieldIndex: relationship.endFieldId,\n          startTable: {\n            x: tables[relationship.startTableId].x,\n            y: tables[relationship.startTableId].y,\n          },\n          endTable: {\n            x: tables[relationship.endTableId].x,\n            y: tables[relationship.endTableId].y,\n          },\n        })}\n        stroke=\"gray\"\n        fill=\"none\"\n        strokeWidth={2}\n      />\n      {pathRef.current && (\n        <>\n          <circle cx={start.x} cy={start.y} r=\"12\" fill=\"grey\" />\n          <text\n            x={start.x}\n            y={start.y}\n            fill=\"white\"\n            strokeWidth=\"0.5\"\n            textAnchor=\"middle\"\n            alignmentBaseline=\"middle\"\n          >\n            {cardinalityStart}\n          </text>\n          <circle cx={end.x} cy={end.y} r=\"12\" fill=\"grey\" />\n          <text\n            x={end.x}\n            y={end.y}\n            fill=\"white\"\n            strokeWidth=\"0.5\"\n            textAnchor=\"middle\"\n            alignmentBaseline=\"middle\"\n          >\n            {cardinalityEnd}\n          </text>\n        </>\n      )}\n    </g>\n  );\n}\n\nexport default function SimpleCanvas({ diagram, zoom }) {\n  const [tables, setTables] = useState(diagram.tables);\n  const [dragging, setDragging] = useState(-1);\n  const [offset, setOffset] = useState({ x: 0, y: 0 });\n\n  const grabTable = (e, id) => {\n    setDragging(id);\n    setOffset({\n      x: e.clientX - tables[id].x,\n      y: e.clientY - tables[id].y,\n    });\n  };\n\n  const moveTable = (e) => {\n    if (dragging !== -1) {\n      const dx = e.clientX - offset.x;\n      const dy = e.clientY - offset.y;\n      setTables((prev) =>\n        prev.map((table, i) =>\n          i === dragging ? { ...table, x: dx, y: dy } : table,\n        ),\n      );\n    }\n  };\n\n  const releaseTable = () => {\n    setDragging(-1);\n    setOffset({ x: 0, y: 0 });\n  };\n\n  return (\n    <svg\n      className=\"w-full h-full cursor-grab rounded-3xl\"\n      onPointerUp={(e) => e.isPrimary && releaseTable()}\n      onPointerMove={(e) => e.isPrimary && moveTable(e)}\n      onPointerLeave={(e) => e.isPrimary && releaseTable()}\n    >\n      <defs>\n        <pattern\n          id=\"pattern-circles\"\n          x=\"0\"\n          y=\"0\"\n          width=\"22\"\n          height=\"22\"\n          patternUnits=\"userSpaceOnUse\"\n          patternContentUnits=\"userSpaceOnUse\"\n        >\n          <circle\n            id=\"pattern-circle\"\n            cx=\"4\"\n            cy=\"4\"\n            r=\"0.85\"\n            fill=\"rgb(99, 152, 191)\"\n          ></circle>\n        </pattern>\n      </defs>\n      <rect\n        x=\"0\"\n        y=\"0\"\n        width=\"100%\"\n        height=\"100%\"\n        fill=\"url(#pattern-circles)\"\n      ></rect>\n      <g\n        style={{\n          transform: `scale(${zoom})`,\n          transformOrigin: \"top left\",\n        }}\n      >\n        {diagram.relationships.map((r, i) => (\n          <Relationship key={i} relationship={r} tables={tables} />\n        ))}\n        {tables.map((t, i) => (\n          <Table key={i} table={t} grab={(e) => grabTable(e, i)} />\n        ))}\n      </g>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/SortableList/DragHandle.jsx",
    "content": "import { IconHandle } from \"@douyinfe/semi-icons\";\nimport { useSortable } from \"@dnd-kit/sortable\";\n\nexport function DragHandle({ id, readOnly }) {\n  const { listeners } = useSortable({ id });\n\n  return (\n    <div\n      className={`opacity-50 mt-1.5 ${readOnly ? \"cursor-not-allowed\" : \"cursor-move\"}`}\n      {...(!readOnly && listeners)}\n    >\n      <IconHandle />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SortableList/SortableItem.jsx",
    "content": "import { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\n\nexport function SortableItem({ children, id }) {\n  const { attributes, setNodeRef, transform, transition } = useSortable({\n    id,\n  });\n  const style = {\n    transform: CSS.Translate.toString(transform),\n    transition,\n  };\n\n  return (\n    <div ref={setNodeRef} style={style} {...attributes}>\n      {children}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SortableList/SortableList.jsx",
    "content": "import {\n  closestCenter,\n  DndContext,\n  PointerSensor,\n  useSensor,\n  useSensors,\n} from \"@dnd-kit/core\";\nimport {\n  SortableContext,\n  arrayMove,\n  verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { SortableItem } from \"./SortableItem\";\n\nexport function SortableList({\n  items,\n  onChange,\n  afterChange,\n  renderItem,\n  keyPrefix,\n}) {\n  const sensors = useSensors(useSensor(PointerSensor));\n\n  const handleDragEnd = (event) => {\n    const { active, over } = event;\n\n    if (active.id !== over.id) {\n      const oldIndex = items.findIndex((item) => item.id === active.id);\n      const newIndex = items.findIndex((item) => item.id === over.id);\n      const newItems = arrayMove(items, oldIndex, newIndex);\n      onChange(newItems);\n      afterChange();\n    }\n  };\n\n  return (\n    <DndContext\n      sensors={sensors}\n      collisionDetection={closestCenter}\n      onDragEnd={handleDragEnd}\n    >\n      <SortableContext items={items} strategy={verticalListSortingStrategy}>\n        {items.map((item, i) => (\n          <SortableItem\n            id={item.id}\n            key={`${keyPrefix}-sortable-item-${item.id}`}\n          >\n            {renderItem(item, i)}\n          </SortableItem>\n        ))}\n      </SortableContext>\n    </DndContext>\n  );\n}\n"
  },
  {
    "path": "src/components/Thumbnail.jsx",
    "content": "import {\n  tableFieldHeight,\n  tableHeaderHeight,\n  noteWidth,\n  noteRadius,\n  noteFold,\n  gridSize,\n  gridCircleRadius,\n} from \"../data/constants\";\n\nexport default function Thumbnail({ diagram, i, zoom, theme }) {\n  return (\n    <svg\n      className={`${\n        theme === \"dark\" ? \"bg-[#222229]\" : \"bg-white\"\n      } w-full h-full rounded-md text-color`}\n    >\n      <defs>\n        <pattern\n          id={\"pattern-grid-\" + i}\n          x={-gridCircleRadius}\n          y={-gridCircleRadius}\n          width={gridSize * zoom}\n          height={gridSize * zoom}\n          patternUnits=\"userSpaceOnUse\"\n          patternContentUnits=\"userSpaceOnUse\"\n        >\n          <circle\n            cx={gridCircleRadius * zoom}\n            cy={gridCircleRadius * zoom}\n            r={gridCircleRadius * zoom}\n            fill=\"rgb(99, 152, 191)\"\n            opacity=\"1\"\n          />\n        </pattern>\n      </defs>\n      <rect\n        x=\"0\"\n        y=\"0\"\n        width=\"100%\"\n        height=\"100%\"\n        fill={\"url(#pattern-grid-\" + i + \")\"}\n      ></rect>\n      <g\n        style={{\n          transform: `scale(${zoom})`,\n        }}\n      >\n        {diagram.subjectAreas?.map((a) => (\n          <foreignObject\n            key={a.id}\n            x={a.x}\n            y={a.y}\n            width={a.width > 0 ? a.width : 0}\n            height={a.height > 0 ? a.height : 0}\n          >\n            <div className=\"border border-slate-400 w-full h-full rounded-xs relative\">\n              <div\n                className=\"opacity-40 w-fill h-full\"\n                style={{ backgroundColor: a.color }}\n              />\n            </div>\n            <div className=\"text-color absolute top-1 left-2 select-none\">\n              {a.name}\n            </div>\n          </foreignObject>\n        ))}\n        {diagram.tables?.map((table, i) => {\n          const height =\n            table.fields.length * tableFieldHeight + tableHeaderHeight + 7;\n          return (\n            <foreignObject\n              x={table.x}\n              y={table.y}\n              width={200}\n              height={height}\n              key={i}\n            >\n              <div\n                className={`border rounded-md ${\n                  theme === \"dark\"\n                    ? \"bg-zinc-800\"\n                    : \"border-zinc-300 bg-zinc-100\"\n                }`}\n              >\n                <div\n                  className=\"h-2 w-full rounded-t-sm\"\n                  style={{ backgroundColor: table.color }}\n                />\n                <div className=\"rounded-b-[3px]\">\n                  <div\n                    className={`font-bold py-1 px-2 border-b ${\n                      theme === \"dark\" ? \"bg-zinc-900\" : \"bg-zinc-200\"\n                    } border-gray-300`}\n                  >\n                    {table.name}\n                  </div>\n                  {table.fields.map((f, j) => (\n                    <div\n                      className={`flex justify-between items-center py-1 px-2 ${\n                        j < table.fields.length - 1 ? \"border-b\" : \"\"\n                      }`}\n                      key={j}\n                    >\n                      <div className=\"flex items-center justify-start\">\n                        <div\n                          className={`w-[6px] h-[6px] bg-[#2f68adcc] rounded-full me-2`}\n                        ></div>\n                        <div>{f.name}</div>\n                      </div>\n                      <div className=\"text-zinc-500\">{f.type}</div>\n                    </div>\n                  ))}\n                </div>\n              </div>\n            </foreignObject>\n          );\n        })}\n        {diagram.notes?.map((n) => {\n          const x = n.x;\n          const y = n.y;\n          const h = n.height;\n          const w = n.width ?? noteWidth;\n          return (\n            <g key={n.id}>\n              <path\n                d={`M${x + noteFold} ${y} L${x + w - noteRadius} ${y} A${noteRadius} ${noteRadius} 0 0 1 ${\n                  x + w\n                } ${y + noteRadius} L${x + w} ${y + h - noteRadius} A${noteRadius} ${noteRadius} 0 0 1 ${\n                  x + w - noteRadius\n                } ${y + h} L${x + noteRadius} ${y + h} A${noteRadius} ${noteRadius} 0 0 1 ${x} ${\n                  y + h - noteRadius\n                } L${x} ${y + noteFold}`}\n                fill={n.color}\n                stroke=\"rgb(168 162 158)\"\n                strokeLinejoin=\"round\"\n                strokeWidth=\"0.5\"\n              />\n              <path\n                d={`M${x} ${y + noteFold} L${x + noteFold - noteRadius} ${\n                  y + noteFold\n                } A${noteRadius} ${noteRadius} 0 0 0 ${x + noteFold} ${y + noteFold - noteRadius} L${\n                  x + noteFold\n                } ${y} L${x} ${y + noteFold} Z`}\n                fill={n.color}\n                stroke={\"rgb(168 162 158)\"}\n                strokeLinejoin=\"round\"\n                strokeWidth=\"0.5\"\n              />\n              <foreignObject x={x} y={y} width={w} height={h}>\n                <div className=\"text-gray-900 w-full h-full px-4 py-2\">\n                  <label htmlFor={`note_${n.id}`} className=\"ms-4\">\n                    {n.title}\n                  </label>\n                  <div className=\"mt-[2px]\">{n.content}</div>\n                </div>\n              </foreignObject>\n            </g>\n          );\n        })}\n      </g>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/Workspace.jsx",
    "content": "import { useState, useEffect, useCallback, createContext } from \"react\";\nimport ControlPanel from \"./EditorHeader/ControlPanel\";\nimport Canvas from \"./EditorCanvas/Canvas\";\nimport { CanvasContextProvider } from \"../context/CanvasContext\";\nimport SidePanel from \"./EditorSidePanel/SidePanel\";\nimport { DB, State } from \"../data/constants\";\nimport { db } from \"../data/db\";\nimport {\n  useLayout,\n  useSettings,\n  useTransform,\n  useDiagram,\n  useUndoRedo,\n  useAreas,\n  useNotes,\n  useTypes,\n  useSaveState,\n  useEnums,\n} from \"../hooks\";\nimport FloatingControls from \"./FloatingControls\";\nimport { Button, Modal, Tag } from \"@douyinfe/semi-ui\";\nimport { IconAlertTriangle } from \"@douyinfe/semi-icons\";\nimport { useTranslation } from \"react-i18next\";\nimport { databases } from \"../data/databases\";\nimport { isRtl } from \"../i18n/utils/rtl\";\nimport {\n  useMatch,\n  useNavigate,\n  useParams,\n  useSearchParams,\n} from \"react-router-dom\";\nimport { get, SHARE_FILENAME } from \"../api/gists\";\nimport { nanoid } from \"nanoid\";\n\nexport const IdContext = createContext({\n  gistId: \"\",\n  setGistId: () => {},\n  version: \"\",\n  setVersion: () => {},\n});\n\nconst SIDEPANEL_MIN_WIDTH = 384;\n\nexport default function WorkSpace() {\n  const [gistId, setGistId] = useState(\"\");\n  const [version, setVersion] = useState(\"\");\n  const [loadedFromGistId, setLoadedFromGistId] = useState(\"\");\n  const [title, setTitle] = useState(\"Untitled Diagram\");\n  const [resize, setResize] = useState(false);\n  const [width, setWidth] = useState(SIDEPANEL_MIN_WIDTH);\n  const [lastSaved, setLastSaved] = useState(\"\");\n  const [showSelectDbModal, setShowSelectDbModal] = useState(false);\n  const [showRestoreModal, setShowRestoreModal] = useState(false);\n  const [selectedDb, setSelectedDb] = useState(\"\");\n  const { layout, setLayout } = useLayout();\n  const { settings } = useSettings();\n  const { types, setTypes } = useTypes();\n  const { areas, setAreas } = useAreas();\n  const { notes, setNotes } = useNotes();\n  const { saveState, setSaveState } = useSaveState();\n  const { transform, setTransform } = useTransform();\n  const { enums, setEnums } = useEnums();\n  const {\n    tables,\n    relationships,\n    setTables,\n    setRelationships,\n    database,\n    setDatabase,\n  } = useDiagram();\n  const { undoStack, redoStack, setUndoStack, setRedoStack } = useUndoRedo();\n  const { t, i18n } = useTranslation();\n  let [searchParams, setSearchParams] = useSearchParams();\n  const { id: loadedDiagramId } = useParams();\n  const isDiagram = useMatch(\"/editor/diagrams/:id\");\n  const isTemplate = useMatch(\"/editor/templates/:id\");\n\n  const navigate = useNavigate();\n\n  const handleResize = (e) => {\n    if (!resize) return;\n    const w = isRtl(i18n.language) ? window.innerWidth - e.clientX : e.clientX;\n    if (w > SIDEPANEL_MIN_WIDTH) setWidth(w);\n  };\n\n  const save = useCallback(async () => {\n    if (searchParams.has(\"shareId\")) {\n      searchParams.delete(\"shareId\");\n      setSearchParams(searchParams, { replace: true });\n    }\n\n    if (isTemplate || (!loadedDiagramId && !isTemplate && !isDiagram)) {\n      const diagramId = crypto.randomUUID();\n      await db.diagrams\n        .add({\n          diagramId,\n          database: database,\n          name: title,\n          gistId: gistId ?? \"\",\n          lastModified: new Date(),\n          tables: tables,\n          references: relationships,\n          notes: notes,\n          areas: areas,\n          pan: transform.pan,\n          zoom: transform.zoom,\n          loadedFromGistId: loadedFromGistId,\n          ...(databases[database].hasEnums && { enums: enums }),\n          ...(databases[database].hasTypes && { types: types }),\n        })\n        .then(() => {\n          navigate(`/editor/diagrams/${diagramId}`, { replace: true });\n          setSaveState(State.SAVED);\n          setLastSaved(new Date().toLocaleString());\n        });\n    } else {\n      await db.diagrams\n        .where(\"diagramId\")\n        .equals(loadedDiagramId)\n        .modify({\n          database: database,\n          name: title,\n          lastModified: new Date(),\n          tables: tables,\n          references: relationships,\n          notes: notes,\n          areas: areas,\n          gistId: gistId ?? \"\",\n          pan: transform.pan,\n          zoom: transform.zoom,\n          loadedFromGistId: loadedFromGistId,\n          ...(databases[database].hasEnums && { enums: enums }),\n          ...(databases[database].hasTypes && { types: types }),\n        })\n        .then(() => {\n          setSaveState(State.SAVED);\n          setLastSaved(new Date().toLocaleString());\n        });\n    }\n  }, [\n    searchParams,\n    setSearchParams,\n    tables,\n    relationships,\n    notes,\n    areas,\n    types,\n    title,\n    transform,\n    setSaveState,\n    database,\n    enums,\n    gistId,\n    loadedFromGistId,\n    isDiagram,\n    isTemplate,\n    loadedDiagramId,\n    navigate,\n  ]);\n\n  const load = useCallback(async () => {\n    const loadLatestDiagram = async () => {\n      await db.diagrams\n        .orderBy(\"lastModified\")\n        .last()\n        .then((diagram) => {\n          if (diagram) {\n            if (diagram.database) {\n              setDatabase(diagram.database);\n            } else {\n              setDatabase(DB.GENERIC);\n            }\n            setGistId(diagram.gistId);\n            setLoadedFromGistId(diagram.loadedFromGistId);\n            setTitle(diagram.name);\n            setTables(diagram.tables);\n            setRelationships(diagram.references);\n            setNotes(diagram.notes);\n            setAreas(diagram.areas);\n            setTransform({ pan: diagram.pan, zoom: diagram.zoom });\n            if (databases[database].hasTypes) {\n              if (diagram.types) {\n                setTypes(\n                  diagram.types.map((t) =>\n                    t.id\n                      ? t\n                      : {\n                          ...t,\n                          id: nanoid(),\n                          fields: t.fields.map((f) =>\n                            f.id ? f : { ...f, id: nanoid() },\n                          ),\n                        },\n                  ),\n                );\n              } else {\n                setTypes([]);\n              }\n            }\n            if (databases[database].hasEnums) {\n              setEnums(\n                diagram.enums.map((e) =>\n                  !e.id ? { ...e, id: nanoid() } : e,\n                ) ?? [],\n              );\n            }\n            navigate(`/editor/diagrams/${diagram.diagramId}`, {\n              replace: true,\n            });\n          } else {\n            if (selectedDb === \"\") setShowSelectDbModal(true);\n          }\n        })\n        .catch((error) => {\n          console.log(error);\n        });\n    };\n\n    const loadDiagram = async (id) => {\n      const diagram = await db.diagrams.where(\"diagramId\").equals(id).first();\n\n      if (!diagram) return;\n\n      if (diagram.database) {\n        setDatabase(diagram.database);\n      } else {\n        setDatabase(DB.GENERIC);\n      }\n      setGistId(diagram.gistId);\n      setLoadedFromGistId(diagram.loadedFromGistId);\n      setTitle(diagram.name);\n      setTables(diagram.tables);\n      setRelationships(diagram.references);\n      setAreas(diagram.areas);\n      setNotes(diagram.notes);\n      setTransform({\n        pan: diagram.pan,\n        zoom: diagram.zoom,\n      });\n      setUndoStack([]);\n      setRedoStack([]);\n      if (databases[database].hasTypes) {\n        if (diagram.types) {\n          setTypes(\n            diagram.types.map((t) =>\n              t.id\n                ? t\n                : {\n                    ...t,\n                    id: nanoid(),\n                    fields: t.fields.map((f) =>\n                      f.id ? f : { ...f, id: nanoid() },\n                    ),\n                  },\n            ),\n          );\n        } else {\n          setTypes([]);\n        }\n      }\n      if (databases[database].hasEnums) {\n        setEnums(\n          diagram.enums.map((e) => (!e.id ? { ...e, id: nanoid() } : e)) ?? [],\n        );\n      }\n    };\n\n    const loadTemplate = async (id) => {\n      const template = await db.templates\n        .where(\"templateId\")\n        .equals(id)\n        .first();\n\n      if (template) {\n        if (template.database) {\n          setDatabase(template.database);\n        } else {\n          setDatabase(DB.GENERIC);\n        }\n        setTitle(template.title);\n        setTables(template.tables);\n        setRelationships(template.relationships);\n        setAreas(template.subjectAreas);\n        setNotes(template.notes);\n        setTransform({\n          zoom: 1,\n          pan: { x: 0, y: 0 },\n        });\n        setUndoStack([]);\n        setRedoStack([]);\n        if (databases[database].hasTypes) {\n          if (template.types) {\n            setTypes(\n              template.types.map((t) =>\n                t.id\n                  ? t\n                  : {\n                      ...t,\n                      id: nanoid(),\n                      fields: t.fields.map((f) =>\n                        f.id ? f : { ...f, id: nanoid() },\n                      ),\n                    },\n              ),\n            );\n          } else {\n            setTypes([]);\n          }\n        }\n        if (databases[database].hasEnums) {\n          setEnums(\n            template.enums.map((e) => (!e.id ? { ...e, id: nanoid() } : e)) ??\n              [],\n          );\n        }\n      } else {\n        if (selectedDb === \"\") setShowSelectDbModal(true);\n      }\n    };\n\n    const loadFromGist = async (shareId, diagramId = null) => {\n      try {\n        const { data } = await get(shareId);\n        const parsedDiagram = JSON.parse(data.files[SHARE_FILENAME].content);\n        setUndoStack([]);\n        setRedoStack([]);\n        setGistId(shareId);\n        setLoadedFromGistId(shareId);\n        setDatabase(parsedDiagram.database);\n        setTitle(parsedDiagram.title);\n        setTables(parsedDiagram.tables);\n        setRelationships(parsedDiagram.relationships);\n        setNotes(parsedDiagram.notes);\n        setAreas(parsedDiagram.subjectAreas);\n        setTransform(parsedDiagram.transform);\n        if (databases[parsedDiagram.database].hasTypes) {\n          if (parsedDiagram.types) {\n            setTypes(\n              parsedDiagram.types.map((t) =>\n                t.id\n                  ? t\n                  : {\n                      ...t,\n                      id: nanoid(),\n                      fields: t.fields.map((f) =>\n                        f.id ? f : { ...f, id: nanoid() },\n                      ),\n                    },\n              ),\n            );\n          } else {\n            setTypes([]);\n          }\n        }\n        if (databases[parsedDiagram.database].hasEnums) {\n          setEnums(\n            parsedDiagram.enums.map((e) =>\n              !e.id ? { ...e, id: nanoid() } : e,\n            ) ?? [],\n          );\n        }\n        if (diagramId) {\n          navigate(`/editor/diagrams/${diagramId}`, {\n            replace: true,\n          });\n        }\n      } catch (e) {\n        console.log(e);\n        setSaveState(State.FAILED_TO_LOAD);\n      }\n    };\n\n    const shareId = searchParams.get(\"shareId\");\n    if (shareId) {\n      const existingDiagram = await db.diagrams.get({\n        loadedFromGistId: shareId,\n      });\n\n      await loadFromGist(shareId, existingDiagram?.diagramId || null);\n      return;\n    }\n\n    if (!loadedDiagramId) {\n      await loadLatestDiagram();\n      return;\n    }\n\n    if (isDiagram && loadedDiagramId) {\n      await loadDiagram(loadedDiagramId);\n      return;\n    }\n\n    if (isTemplate && loadedDiagramId) {\n      await loadTemplate(loadedDiagramId);\n      return;\n    }\n  }, [\n    setTransform,\n    setRedoStack,\n    setUndoStack,\n    setRelationships,\n    setTables,\n    setAreas,\n    setNotes,\n    setTypes,\n    setDatabase,\n    database,\n    setEnums,\n    selectedDb,\n    setSaveState,\n    searchParams,\n    navigate,\n    isDiagram,\n    isTemplate,\n    loadedDiagramId,\n  ]);\n\n  const returnToCurrentDiagram = async () => {\n    await load();\n    setLayout((prev) => ({ ...prev, readOnly: false }));\n    setVersion(null);\n  };\n\n  useEffect(() => {\n    if (\n      tables?.length === 0 &&\n      areas?.length === 0 &&\n      notes?.length === 0 &&\n      types?.length === 0\n    )\n      return;\n\n    if (settings.autosave) {\n      setSaveState(State.SAVING);\n    }\n  }, [\n    undoStack,\n    redoStack,\n    settings.autosave,\n    tables?.length,\n    areas?.length,\n    notes?.length,\n    types?.length,\n    relationships?.length,\n    transform.zoom,\n    title,\n    gistId,\n    setSaveState,\n  ]);\n\n  useEffect(() => {\n    if (layout.readOnly) return;\n\n    if (saveState !== State.SAVING) return;\n\n    save();\n  }, [saveState, layout, save]);\n\n  useEffect(() => {\n    document.title = \"Editor | drawDB\";\n\n    load();\n  }, [load]);\n\n  return (\n    <div className=\"h-full flex flex-col overflow-hidden theme\">\n      <IdContext.Provider value={{ gistId, setGistId, version, setVersion }}>\n        <ControlPanel\n          title={title}\n          setTitle={setTitle}\n          lastSaved={lastSaved}\n          setLastSaved={setLastSaved}\n        />\n      </IdContext.Provider>\n      <div\n        className=\"flex h-full overflow-y-auto\"\n        onPointerUp={(e) => e.isPrimary && setResize(false)}\n        onPointerLeave={(e) => e.isPrimary && setResize(false)}\n        onPointerMove={(e) => e.isPrimary && handleResize(e)}\n        onPointerDown={(e) => {\n          // Required for onPointerLeave to trigger when a touch pointer leaves\n          // https://stackoverflow.com/a/70976017/1137077\n          e.target.releasePointerCapture(e.pointerId);\n        }}\n        style={isRtl(i18n.language) ? { direction: \"rtl\" } : {}}\n      >\n        {layout.sidebar && (\n          <SidePanel resize={resize} setResize={setResize} width={width} />\n        )}\n        <div className=\"relative w-full h-full overflow-hidden\">\n          <CanvasContextProvider className=\"h-full w-full\">\n            <Canvas saveState={saveState} setSaveState={setSaveState} />\n          </CanvasContextProvider>\n          {version && (\n            <div className=\"absolute right-8 top-2 space-x-2\">\n              <Button\n                icon={<i className=\"fa-solid fa-rotate-right mt-0.5\"></i>}\n                onClick={() => setShowRestoreModal(true)}\n              >\n                {t(\"restore_version\")}\n              </Button>\n              <Button\n                type=\"tertiary\"\n                onClick={returnToCurrentDiagram}\n                icon={<i className=\"bi bi-arrow-return-right mt-1\"></i>}\n              >\n                {t(\"return_to_current\")}\n              </Button>\n            </div>\n          )}\n          {!(layout.sidebar || layout.toolbar || layout.header) && (\n            <div className=\"fixed right-5 bottom-4\">\n              <FloatingControls />\n            </div>\n          )}\n        </div>\n      </div>\n      <Modal\n        centered\n        size=\"medium\"\n        closable={false}\n        hasCancel={false}\n        title={t(\"pick_db\")}\n        okText={t(\"confirm\")}\n        visible={showSelectDbModal}\n        onOk={() => {\n          if (selectedDb === \"\") return;\n          setDatabase(selectedDb);\n          setShowSelectDbModal(false);\n        }}\n        okButtonProps={{ disabled: selectedDb === \"\" }}\n      >\n        <div className=\"grid grid-cols-3 gap-4 place-content-center\">\n          {Object.values(databases).map((x) => (\n            <div\n              key={x.name}\n              onClick={() => setSelectedDb(x.label)}\n              className={`space-y-3 p-3 rounded-md border-2 select-none ${\n                settings.mode === \"dark\"\n                  ? \"bg-zinc-700 hover:bg-zinc-600\"\n                  : \"bg-zinc-100 hover:bg-zinc-200\"\n              } ${selectedDb === x.label ? \"border-zinc-400\" : \"border-transparent\"}`}\n            >\n              <div className=\"flex items-center justify-between\">\n                <div className=\"font-semibold\">{x.name}</div>\n                {x.beta && (\n                  <Tag size=\"small\" color=\"light-blue\">\n                    Beta\n                  </Tag>\n                )}\n              </div>\n              {x.image && (\n                <img\n                  src={x.image}\n                  className=\"h-8\"\n                  style={{\n                    filter:\n                      \"opacity(0.4) drop-shadow(0 0 0 white) drop-shadow(0 0 0 white)\",\n                  }}\n                />\n              )}\n              <div className=\"text-xs\">{x.description}</div>\n            </div>\n          ))}\n        </div>\n      </Modal>\n      <Modal\n        visible={showRestoreModal}\n        centered\n        closable\n        onCancel={() => setShowRestoreModal(false)}\n        title={\n          <span className=\"flex items-center gap-2\">\n            <IconAlertTriangle className=\"text-amber-400\" size=\"extra-large\" />{\" \"}\n            {t(\"restore_version\")}\n          </span>\n        }\n        okText={t(\"continue\")}\n        cancelText={t(\"cancel\")}\n        onOk={() => {\n          setLayout((prev) => ({ ...prev, readOnly: false }));\n          setShowRestoreModal(false);\n          setVersion(null);\n        }}\n      >\n        {t(\"restore_warning\")}\n      </Modal>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/context/AreasContext.jsx",
    "content": "import { Toast } from \"@douyinfe/semi-ui\";\nimport { createContext, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Action, ObjectType, defaultBlue } from \"../data/constants\";\nimport { useSelect, useTransform, useUndoRedo } from \"../hooks\";\n\nexport const AreasContext = createContext(null);\n\nexport default function AreasContextProvider({ children }) {\n  const { t } = useTranslation();\n  const [areas, setAreas] = useState([]);\n  const { transform } = useTransform();\n  const { selectedElement, setSelectedElement } = useSelect();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n\n  const addArea = (data, addToHistory = true) => {\n    if (data) {\n      setAreas((prev) => {\n        const temp = prev.slice();\n        temp.splice(data.id, 0, data);\n        return temp.map((t, i) => ({ ...t, id: i }));\n      });\n    } else {\n      const width = 200;\n      const height = 200;\n      setAreas((prev) => [\n        ...prev,\n        {\n          id: prev.length,\n          name: `area_${prev.length}`,\n          x: transform.pan.x - width / 2,\n          y: transform.pan.y - height / 2,\n          width,\n          height,\n          color: defaultBlue,\n          locked: false,\n        },\n      ]);\n    }\n    if (addToHistory) {\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.ADD,\n          element: ObjectType.AREA,\n          message: t(\"add_area\"),\n        },\n      ]);\n      setRedoStack([]);\n    }\n  };\n\n  const deleteArea = (id, addToHistory = true) => {\n    if (addToHistory) {\n      Toast.success(t(\"area_deleted\"));\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.DELETE,\n          element: ObjectType.AREA,\n          data: areas[id],\n          message: t(\"delete_area\", { areaName: areas[id].name }),\n        },\n      ]);\n      setRedoStack([]);\n    }\n    setAreas((prev) =>\n      prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i })),\n    );\n    if (id === selectedElement.id) {\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: ObjectType.NONE,\n        id: -1,\n        open: false,\n      }));\n    }\n  };\n\n  const updateArea = (id, values) => {\n    setAreas((prev) =>\n      prev.map((t) => {\n        if (t.id === id) {\n          return {\n            ...t,\n            ...values,\n          };\n        }\n        return t;\n      }),\n    );\n  };\n\n  return (\n    <AreasContext.Provider\n      value={{\n        areas,\n        setAreas,\n        updateArea,\n        addArea,\n        deleteArea,\n        areasCount: areas.length,\n      }}\n    >\n      {children}\n    </AreasContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/context/CanvasContext.jsx",
    "content": "import { useTransform } from \"../hooks\";\nimport { createContext, useCallback, useMemo, useRef, useState } from \"react\";\nimport { useEventListener, useResizeObserver } from \"usehooks-ts\";\n\nexport const CanvasContext = createContext({\n  canvas: {\n    screenSize: {\n      x: 0,\n      y: 0,\n    },\n    viewBox: new DOMRect(),\n  },\n  coords: {\n    toDiagramSpace(coords) {\n      return coords;\n    },\n    toScreenSpace(coords) {\n      return coords;\n    },\n  },\n  pointer: {\n    spaces: {\n      screen: {\n        x: 0,\n        y: 0,\n      },\n      diagram: {\n        x: 0,\n        y: 0,\n      },\n    },\n    style: \"default\",\n    setStyle() {},\n  },\n});\n\nexport function CanvasContextProvider({ children, ...attrs }) {\n  const canvasWrapRef = useRef(null);\n  const { transform } = useTransform();\n  const canvasSize = useResizeObserver({\n    ref: canvasWrapRef,\n    box: \"content-box\",\n  });\n  const screenSize = useMemo(\n    () => ({\n      x: canvasSize.width ?? 0,\n      y: canvasSize.height ?? 0,\n    }),\n    [canvasSize.height, canvasSize.width],\n  );\n  const viewBoxSize = useMemo(\n    () => ({\n      x: screenSize.x / transform.zoom,\n      y: screenSize.y / transform.zoom,\n    }),\n    [screenSize.x, screenSize.y, transform.zoom],\n  );\n  const viewBox = useMemo(\n    () =>\n      new DOMRect(\n        transform.pan.x - viewBoxSize.x / 2,\n        transform.pan.y - viewBoxSize.y / 2,\n        viewBoxSize.x,\n        viewBoxSize.y,\n      ),\n    [transform.pan.x, transform.pan.y, viewBoxSize.x, viewBoxSize.y],\n  );\n\n  const toDiagramSpace = useCallback(\n    (coord) => ({\n      x:\n        typeof coord.x === \"number\"\n          ? (coord.x / screenSize.x) * viewBox.width + viewBox.left\n          : undefined,\n      y:\n        typeof coord.y === \"number\"\n          ? (coord.y / screenSize.y) * viewBox.height + viewBox.top\n          : undefined,\n    }),\n    [\n      screenSize.x,\n      screenSize.y,\n      viewBox.height,\n      viewBox.left,\n      viewBox.top,\n      viewBox.width,\n    ],\n  );\n\n  const toScreenSpace = useCallback(\n    (coord) => ({\n      x:\n        typeof coord.x === \"number\"\n          ? ((coord.x - viewBox.left) / viewBox.width) * screenSize.x\n          : undefined,\n      y:\n        typeof coord.y === \"number\"\n          ? ((coord.y - viewBox.top) / viewBox.height) * screenSize.y\n          : undefined,\n    }),\n    [\n      screenSize.x,\n      screenSize.y,\n      viewBox.height,\n      viewBox.left,\n      viewBox.top,\n      viewBox.width,\n    ],\n  );\n\n  const [pointerScreenCoords, setPointerScreenCoords] = useState({\n    x: 0,\n    y: 0,\n  });\n  const pointerDiagramCoords = useMemo(\n    () => toDiagramSpace(pointerScreenCoords),\n    [pointerScreenCoords, toDiagramSpace],\n  );\n  const [pointerStyle, setPointerStyle] = useState(\"default\");\n\n  /**\n   * @param {PointerEvent} e\n   */\n  function detectPointerMovement(e) {\n    const targetElm = /** @type {HTMLElement | null} */ (e.currentTarget);\n    if (!e.isPrimary || !targetElm) return;\n\n    const canvasBounds = targetElm.getBoundingClientRect();\n\n    setPointerScreenCoords({\n      x: e.clientX - canvasBounds.left,\n      y: e.clientY - canvasBounds.top,\n    });\n  }\n\n  // Important for touch screen devices!\n  useEventListener(\"pointerdown\", detectPointerMovement, canvasWrapRef);\n\n  useEventListener(\"pointermove\", detectPointerMovement, canvasWrapRef);\n\n  const contextValue = {\n    canvas: {\n      screenSize,\n      viewBox,\n    },\n    coords: {\n      toDiagramSpace,\n      toScreenSpace,\n    },\n    pointer: {\n      spaces: {\n        screen: pointerScreenCoords,\n        diagram: pointerDiagramCoords,\n      },\n      style: pointerStyle,\n      setStyle: setPointerStyle,\n    },\n  };\n\n  return (\n    <CanvasContext.Provider value={contextValue}>\n      <div {...attrs} ref={canvasWrapRef}>\n        {children}\n      </div>\n    </CanvasContext.Provider>\n  )\n}\n"
  },
  {
    "path": "src/context/DiagramContext.jsx",
    "content": "import { createContext, useState } from \"react\";\nimport { Action, DB, ObjectType, defaultBlue } from \"../data/constants\";\nimport { useTransform, useUndoRedo, useSelect } from \"../hooks\";\nimport { Toast } from \"@douyinfe/semi-ui\";\nimport { useTranslation } from \"react-i18next\";\nimport { nanoid } from \"nanoid\";\n\nexport const DiagramContext = createContext(null);\n\nexport default function DiagramContextProvider({ children }) {\n  const { t } = useTranslation();\n  const [database, setDatabase] = useState(DB.GENERIC);\n  const [tables, setTables] = useState([]);\n  const [relationships, setRelationships] = useState([]);\n  const { transform } = useTransform();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const { selectedElement, setSelectedElement } = useSelect();\n\n  const addTable = (data, addToHistory = true) => {\n    const id = nanoid();\n    const newTable = {\n      id,\n      name: `table_${id}`,\n      x: transform.pan.x,\n      y: transform.pan.y,\n      locked: false,\n      fields: [\n        {\n          name: \"id\",\n          type: database === DB.GENERIC ? \"INT\" : \"INTEGER\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: nanoid(),\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: defaultBlue,\n    };\n    if (data) {\n      setTables((prev) => {\n        const temp = prev.slice();\n        temp.splice(data.index || tables.length, 0, data.table);\n        return temp;\n      });\n    } else {\n      setTables((prev) => [...prev, newTable]);\n    }\n    if (addToHistory) {\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          data: data || { table: newTable, index: tables.length - 1 },\n          action: Action.ADD,\n          element: ObjectType.TABLE,\n          message: t(\"add_table\"),\n        },\n      ]);\n      setRedoStack([]);\n    }\n  };\n\n  const deleteTable = (id, addToHistory = true) => {\n    if (addToHistory) {\n      const rels = relationships.reduce((acc, r) => {\n        if (r.startTableId === id || r.endTableId === id) {\n          acc.push(r);\n        }\n        return acc;\n      }, []);\n      const deletedTable = tables.find((t) => t.id === id);\n      const deletedTableIndex = tables.findIndex((t) => t.id === id);\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.DELETE,\n          element: ObjectType.TABLE,\n          data: {\n            table: deletedTable,\n            relationship: rels,\n            index: deletedTableIndex,\n          },\n          message: t(\"delete_table\", { tableName: deletedTable.name }),\n        },\n      ]);\n      setRedoStack([]);\n      Toast.success(t(\"table_deleted\"));\n    }\n    setRelationships((prevR) =>\n      prevR.filter((e) => !(e.startTableId === id || e.endTableId === id)),\n    );\n    setTables((prev) => prev.filter((e) => e.id !== id));\n    if (id === selectedElement.id) {\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: ObjectType.NONE,\n        id: null,\n        open: false,\n      }));\n    }\n  };\n\n  const updateTable = (id, updatedValues) => {\n    setTables((prev) =>\n      prev.map((t) => (t.id === id ? { ...t, ...updatedValues } : t)),\n    );\n  };\n\n  const updateField = (tid, fid, updatedValues) => {\n    setTables((prev) =>\n      prev.map((table) => {\n        if (tid === table.id) {\n          return {\n            ...table,\n            fields: table.fields.map((field) =>\n              fid === field.id ? { ...field, ...updatedValues } : field,\n            ),\n          };\n        }\n        return table;\n      }),\n    );\n  };\n\n  const deleteField = (field, tid, addToHistory = true) => {\n    const { fields, name } = tables.find((t) => t.id === tid);\n    if (addToHistory) {\n      const rels = relationships.reduce((acc, r) => {\n        if (\n          (r.startTableId === tid && r.startFieldId === field.id) ||\n          (r.endTableId === tid && r.endFieldId === field.id)\n        ) {\n          acc.push(r);\n        }\n        return acc;\n      }, []);\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.EDIT,\n          element: ObjectType.TABLE,\n          component: \"field_delete\",\n          tid: tid,\n          data: {\n            field: field,\n            index: fields.findIndex((f) => f.id === field.id),\n            relationship: rels,\n          },\n          message: t(\"edit_table\", {\n            tableName: name,\n            extra: \"[delete field]\",\n          }),\n        },\n      ]);\n      setRedoStack([]);\n    }\n    setRelationships((prev) =>\n      prev.filter(\n        (e) =>\n          !(\n            (e.startTableId === tid && e.startFieldId === field.id) ||\n            (e.endTableId === tid && e.endFieldId === field.id)\n          ),\n      ),\n    );\n    updateTable(tid, {\n      fields: fields.filter((e) => e.id !== field.id),\n    });\n  };\n\n  const addRelationship = (data, addToHistory = true) => {\n    if (addToHistory) {\n      setRelationships((prev) => {\n        setUndoStack((prevUndo) => [\n          ...prevUndo,\n          {\n            action: Action.ADD,\n            element: ObjectType.RELATIONSHIP,\n            data: {\n              relationship: data,\n              index: prevUndo.length,\n            },\n            message: t(\"add_relationship\"),\n          },\n        ]);\n        setRedoStack([]);\n        return [...prev, data];\n      });\n    } else {\n      setRelationships((prev) => {\n        const temp = prev.slice();\n        temp.splice(data.index, 0, data.relationship || data);\n        return temp;\n      });\n    }\n  };\n\n  const deleteRelationship = (id, addToHistory = true) => {\n    if (addToHistory) {\n      const relationshipIndex = relationships.findIndex((r) => r.id === id);\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.DELETE,\n          element: ObjectType.RELATIONSHIP,\n          data: {\n            relationship: relationships[relationshipIndex],\n            index: relationshipIndex,\n          },\n          message: t(\"delete_relationship\", {\n            refName: relationships[relationshipIndex].name,\n          }),\n        },\n      ]);\n      setRedoStack([]);\n    }\n    setRelationships((prev) => prev.filter((e) => e.id !== id));\n  };\n\n  const updateRelationship = (id, updatedValues) => {\n    setRelationships((prev) =>\n      prev.map((t) => (t.id === id ? { ...t, ...updatedValues } : t)),\n    );\n  };\n\n  return (\n    <DiagramContext.Provider\n      value={{\n        tables,\n        setTables,\n        addTable,\n        updateTable,\n        updateField,\n        deleteField,\n        deleteTable,\n        relationships,\n        setRelationships,\n        addRelationship,\n        deleteRelationship,\n        updateRelationship,\n        database,\n        setDatabase,\n        tablesCount: tables.length,\n        relationshipsCount: relationships.length,\n      }}\n    >\n      {children}\n    </DiagramContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/context/EnumsContext.jsx",
    "content": "import { createContext, useState } from \"react\";\nimport { Action, ObjectType } from \"../data/constants\";\nimport { Toast } from \"@douyinfe/semi-ui\";\nimport { useTranslation } from \"react-i18next\";\nimport { useUndoRedo } from \"../hooks\";\nimport { nanoid } from \"nanoid\";\n\nexport const EnumsContext = createContext(null);\n\nexport default function EnumsContextProvider({ children }) {\n  const { t } = useTranslation();\n  const [enums, setEnums] = useState([]);\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n\n  const addEnum = (data, addToHistory = true) => {\n    const newEnum = {\n      id: nanoid(),\n      name: `enum_${enums.length}`,\n      values: [],\n    };\n    if (data) {\n      setEnums((prev) => {\n        const temp = prev.slice();\n        temp.splice(data.index, 0, data.enum);\n        return temp;\n      });\n    } else {\n      setEnums((prev) => [...prev, newEnum]);\n    }\n    if (addToHistory) {\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.ADD,\n          data: {\n            index: enums.length,\n            enum: data?.enum ?? newEnum,\n          },\n          element: ObjectType.ENUM,\n          message: t(\"add_enum\"),\n        },\n      ]);\n      setRedoStack([]);\n    }\n  };\n\n  const deleteEnum = (id, addToHistory = true) => {\n    const enumIndex = enums.findIndex((e) => e.id === id);\n    if (addToHistory) {\n      Toast.success(t(\"enum_deleted\"));\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.DELETE,\n          element: ObjectType.ENUM,\n          data: {\n            index: enumIndex,\n            enum: enums[enumIndex],\n          },\n          message: t(\"delete_enum\", {\n            enumName: enums[enumIndex].name,\n          }),\n        },\n      ]);\n      setRedoStack([]);\n    }\n    setEnums((prev) => prev.filter((e) => e.id !== id));\n  };\n\n  const updateEnum = (id, values) => {\n    setEnums((prev) =>\n      prev.map((e) => (e.id === id ? { ...e, ...values } : e)),\n    );\n  };\n\n  return (\n    <EnumsContext.Provider\n      value={{\n        enums,\n        setEnums,\n        addEnum,\n        updateEnum,\n        deleteEnum,\n        enumsCount: enums.length,\n      }}\n    >\n      {children}\n    </EnumsContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/context/LayoutContext.jsx",
    "content": "import { createContext, useState } from \"react\";\n\nexport const LayoutContext = createContext(null);\n\nexport default function LayoutContextProvider({ children }) {\n  const [layout, setLayout] = useState({\n    header: true,\n    sidebar: true,\n    issues: true,\n    toolbar: true,\n    dbmlEditor: false,\n    readOnly: false,\n  });\n\n  return (\n    <LayoutContext.Provider value={{ layout, setLayout }}>\n      {children}\n    </LayoutContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/context/NotesContext.jsx",
    "content": "import { createContext, useState, useCallback } from \"react\";\nimport {\n  Action,\n  ObjectType,\n  defaultNoteTheme,\n  noteWidth,\n} from \"../data/constants\";\nimport { useUndoRedo, useTransform, useSelect } from \"../hooks\";\nimport { Toast } from \"@douyinfe/semi-ui\";\nimport { useTranslation } from \"react-i18next\";\n\nexport const NotesContext = createContext(null);\n\nexport default function NotesContextProvider({ children }) {\n  const { t } = useTranslation();\n  const [notes, setNotes] = useState([]);\n  const { transform } = useTransform();\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n  const { selectedElement, setSelectedElement } = useSelect();\n\n  const addNote = (data, addToHistory = true) => {\n    if (data) {\n      setNotes((prev) => {\n        const temp = prev.slice();\n        temp.splice(data.id, 0, data);\n        return temp.map((t, i) => ({ ...t, id: i }));\n      });\n    } else {\n      const height = 88;\n      setNotes((prev) => [\n        ...prev,\n        {\n          id: prev.length,\n          x: transform.pan.x,\n          y: transform.pan.y - height / 2,\n          title: `note_${prev.length}`,\n          content: \"\",\n          locked: false,\n          color: defaultNoteTheme,\n          height,\n          width: noteWidth,\n        },\n      ]);\n    }\n    if (addToHistory) {\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.ADD,\n          element: ObjectType.NOTE,\n          message: t(\"add_note\"),\n        },\n      ]);\n      setRedoStack([]);\n    }\n  };\n\n  const deleteNote = (id, addToHistory = true) => {\n    if (addToHistory) {\n      Toast.success(t(\"note_deleted\"));\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.DELETE,\n          element: ObjectType.NOTE,\n          data: notes[id],\n          message: t(\"delete_note\", { noteTitle: notes[id].title }),\n        },\n      ]);\n      setRedoStack([]);\n    }\n    setNotes((prev) =>\n      prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i })),\n    );\n    if (id === selectedElement.id) {\n      setSelectedElement((prev) => ({\n        ...prev,\n        element: ObjectType.NONE,\n        id: -1,\n        open: false,\n      }));\n    }\n  };\n\n  const updateNote = useCallback((id, values) => {\n    setNotes((prev) =>\n      prev.map((t) => {\n        if (t.id === id) {\n          return {\n            ...t,\n            ...values,\n          };\n        }\n        return t;\n      }),\n    );\n  }, []);\n\n  return (\n    <NotesContext.Provider\n      value={{\n        notes,\n        setNotes,\n        updateNote,\n        addNote,\n        deleteNote,\n        notesCount: notes.length,\n      }}\n    >\n      {children}\n    </NotesContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/context/SaveStateContext.jsx",
    "content": "import { createContext, useState } from \"react\";\nimport { State } from \"../data/constants\";\n\nexport const SaveStateContext = createContext(State.NONE);\n\nexport default function SaveStateContextProvider({ children }) {\n  const [saveState, setSaveState] = useState(State.NONE);\n\n  return (\n    <SaveStateContext.Provider value={{ saveState, setSaveState }}>\n      {children}\n    </SaveStateContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/context/SelectContext.jsx",
    "content": "import { createContext, useState } from \"react\";\nimport { ObjectType, Tab } from \"../data/constants\";\n\nexport const SelectContext = createContext(null);\n\nexport default function SelectContextProvider({ children }) {\n  const [selectedElement, setSelectedElement] = useState({\n    element: ObjectType.NONE,\n    id: -1,\n    openDialogue: false,\n    openCollapse: false,\n    currentTab: Tab.TABLES,\n    open: false, // open popover or sidesheet when sidebar is disabled\n    openFromToolbar: false, // this is to handle triggering onClickOutside when sidebar is disabled\n  });\n  const [bulkSelectedElements, setBulkSelectedElements] = useState([]);\n\n  return (\n    <SelectContext.Provider\n      value={{\n        selectedElement,\n        setSelectedElement,\n        bulkSelectedElements,\n        setBulkSelectedElements,\n      }}\n    >\n      {children}\n    </SelectContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/context/SettingsContext.jsx",
    "content": "import { createContext, useEffect, useState } from \"react\";\nimport { tableWidth } from \"../data/constants\";\n\nconst defaultSettings = {\n  strictMode: false,\n  showFieldSummary: true,\n  showGrid: true,\n  snapToGrid: false,\n  showDataTypes: true,\n  mode: \"light\",\n  autosave: true,\n  showCardinality: true,\n  showRelationshipLabels: true,\n  tableWidth: tableWidth,\n  showDebugCoordinates: false,\n  showComments: true,\n};\n\nexport const SettingsContext = createContext(defaultSettings);\n\nexport default function SettingsContextProvider({ children }) {\n  const [settings, setSettings] = useState(defaultSettings);\n\n  useEffect(() => {\n    const settings = localStorage.getItem(\"settings\");\n    if (settings) {\n      setSettings({ ...defaultSettings, ...JSON.parse(settings) });\n    }\n  }, []);\n\n  useEffect(() => {\n    document.body.setAttribute(\"theme-mode\", settings.mode);\n  }, [settings.mode]);\n\n  useEffect(() => {\n    localStorage.setItem(\"settings\", JSON.stringify(settings));\n  }, [settings]);\n\n  return (\n    <SettingsContext.Provider value={{ settings, setSettings }}>\n      {children}\n    </SettingsContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/context/TransformContext.jsx",
    "content": "import { createContext, useCallback, useState } from \"react\";\n\nexport const TransformContext = createContext(null);\n\nexport default function TransformContextProvider({ children }) {\n  const [transform, setTransformInternal] = useState({\n    zoom: 1,\n    pan: { x: 0, y: 0 },\n  });\n\n  /**\n   * @type {typeof DrawDB.TransformContext[\"setTransform\"]}\n   */\n  const setTransform = useCallback(\n    (actionOrValue) => {\n      const clamp = (value, min, max) => Math.max(min, Math.min(max, value));\n      const findFirstNumber = (...values) =>\n        values.find((value) => typeof value === \"number\" && !isNaN(value));\n\n      setTransformInternal((prev) => {\n        if (typeof actionOrValue === \"function\") {\n          actionOrValue = actionOrValue(prev);\n        }\n\n        return {\n          zoom: clamp(\n            findFirstNumber(actionOrValue.zoom, prev.zoom, 1),\n            0.02,\n            5,\n          ),\n          pan: {\n            x: findFirstNumber(actionOrValue.pan?.x, prev.pan?.x, 0),\n            y: findFirstNumber(actionOrValue.pan?.y, prev.pan?.y, 0),\n          },\n        };\n      });\n    },\n    [setTransformInternal],\n  );\n\n  return (\n    <TransformContext.Provider value={{ transform, setTransform }}>\n      {children}\n    </TransformContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/context/TypesContext.jsx",
    "content": "import { createContext, useState } from \"react\";\nimport { Action, ObjectType } from \"../data/constants\";\nimport { useUndoRedo } from \"../hooks\";\nimport { Toast } from \"@douyinfe/semi-ui\";\nimport { useTranslation } from \"react-i18next\";\nimport { nanoid } from \"nanoid\";\n\nexport const TypesContext = createContext(null);\n\nexport default function TypesContextProvider({ children }) {\n  const { t } = useTranslation();\n  const [types, setTypes] = useState([]);\n  const { setUndoStack, setRedoStack } = useUndoRedo();\n\n  const addType = (data, addToHistory = true) => {\n    const id = nanoid();\n    if (data) {\n      setTypes((prev) => {\n        const temp = prev.slice();\n        temp.splice(data.index, 0, data.type);\n        return temp;\n      });\n    } else {\n      setTypes((prev) => [\n        ...prev,\n        {\n          id,\n          name: `type_${prev.length}`,\n          fields: [],\n          comment: \"\",\n        },\n      ]);\n    }\n    if (addToHistory) {\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          data: {\n            index: types.length,\n            type: data?.type ?? {\n              id,\n              name: `type_${prev.length}`,\n              fields: [],\n              comment: \"\",\n            },\n          },\n          action: Action.ADD,\n          element: ObjectType.TYPE,\n          message: t(\"add_type\"),\n        },\n      ]);\n      setRedoStack([]);\n    }\n  };\n\n  const deleteType = (id, addToHistory = true) => {\n    if (addToHistory) {\n      const deletedTypeIndex = types.findIndex((e, i) =>\n        typeof id === \"number\" ? i === id : e.id === id,\n      );\n      Toast.success(t(\"type_deleted\"));\n      setUndoStack((prev) => [\n        ...prev,\n        {\n          action: Action.DELETE,\n          element: ObjectType.TYPE,\n          data: { type: types[deletedTypeIndex], index: deletedTypeIndex },\n          message: t(\"delete_type\", {\n            typeName: types[deletedTypeIndex].name,\n          }),\n        },\n      ]);\n      setRedoStack([]);\n    }\n    setTypes((prev) =>\n      prev.filter((e, i) => (typeof id === \"number\" ? i !== id : e.id !== id)),\n    );\n  };\n\n  const updateType = (id, values) => {\n    setTypes((prev) =>\n      prev.map((item, index) => {\n        const isMatch = typeof id === \"number\" ? index === id : item.id === id;\n\n        return isMatch ? { ...item, ...values } : item;\n      }),\n    );\n  };\n\n  return (\n    <TypesContext.Provider\n      value={{\n        types,\n        setTypes,\n        addType,\n        updateType,\n        deleteType,\n        typesCount: types.length,\n      }}\n    >\n      {children}\n    </TypesContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/context/UndoRedoContext.jsx",
    "content": "import { createContext, useState } from \"react\";\n\nexport const UndoRedoContext = createContext({\n  undoStack: [],\n  setUndoStack: () => {},\n  redoStack: [],\n  setRedoStack: () => {},\n});\n\nexport default function UndoRedoContextProvider({ children }) {\n  const [undoStack, setUndoStack] = useState([]);\n  const [redoStack, setRedoStack] = useState([]);\n\n  return (\n    <UndoRedoContext.Provider\n      value={{ undoStack, redoStack, setUndoStack, setRedoStack }}\n    >\n      {children}\n    </UndoRedoContext.Provider>\n  );\n}\n"
  },
  {
    "path": "src/data/constants.js",
    "content": "export const defaultBlue = \"#175e7a\";\nexport const defaultNoteTheme = \"#fcf7ac\";\nexport const noteWidth = 180;\nexport const noteRadius = 3;\nexport const noteFold = 24;\nexport const darkBgTheme = \"#16161A\";\nexport const stringColor = \"text-orange-500\";\nexport const intColor = \"text-yellow-500\";\nexport const decimalColor = \"text-lime-500\";\nexport const booleanColor = \"text-violet-500\";\nexport const binaryColor = \"text-emerald-500\";\nexport const enumSetColor = \"text-sky-500\";\nexport const documentColor = \"text-indigo-500\";\nexport const networkIdColor = \"text-rose-500\";\nexport const geometricColor = \"text-fuchsia-500\";\nexport const vectorColor = \"text-slate-500\";\nexport const otherColor = \"text-zinc-500\";\nexport const dateColor = \"text-cyan-500\";\nexport const tableHeaderHeight = 50;\nexport const tableWidth = 220;\nexport const gridSize = 24;\nexport const gridCircleRadius = 0.85;\nexport const tableFieldHeight = 36;\nexport const tableColorStripHeight = 7;\nexport const pngExportPixelRatio = 4;\nexport const minAreaSize = 120;\n\nexport const Cardinality = {\n  ONE_TO_ONE: \"one_to_one\",\n  ONE_TO_MANY: \"one_to_many\",\n  MANY_TO_ONE: \"many_to_one\",\n};\n\nexport const Constraint = {\n  NONE: \"No action\",\n  RESTRICT: \"Restrict\",\n  CASCADE: \"Cascade\",\n  SET_NULL: \"Set null\",\n  SET_DEFAULT: \"Set default\",\n};\n\nexport const Tab = {\n  TABLES: \"1\",\n  RELATIONSHIPS: \"2\",\n  AREAS: \"3\",\n  NOTES: \"4\",\n  TYPES: \"5\",\n  ENUMS: \"6\",\n};\n\nexport const ObjectType = {\n  NONE: 0,\n  TABLE: 1,\n  AREA: 2,\n  NOTE: 3,\n  RELATIONSHIP: 4,\n  TYPE: 5,\n  ENUM: 6,\n};\n\nexport const Action = {\n  ADD: 0,\n  MOVE: 1,\n  DELETE: 2,\n  EDIT: 3,\n};\n\nexport const State = {\n  NONE: 0,\n  SAVING: 1,\n  SAVED: 2,\n  LOADING: 3,\n  ERROR: 4,\n  FAILED_TO_LOAD: 5,\n};\n\nexport const MODAL = {\n  NONE: 0,\n  IMG: 1,\n  CODE: 2,\n  IMPORT: 3,\n  RENAME: 4,\n  OPEN: 5,\n  SAVEAS: 6,\n  NEW: 7,\n  IMPORT_SRC: 8,\n  TABLE_WIDTH: 9,\n  LANGUAGE: 10,\n  SHARE: 11,\n};\n\nexport const STATUS = {\n  NONE: 0,\n  WARNING: 1,\n  ERROR: 2,\n  OK: 3,\n};\n\nexport const SIDESHEET = {\n  NONE: 0,\n  TIMELINE: 1,\n  VERSIONS: 2,\n};\n\nexport const DB = {\n  MYSQL: \"mysql\",\n  POSTGRES: \"postgresql\",\n  MSSQL: \"transactsql\",\n  SQLITE: \"sqlite\",\n  MARIADB: \"mariadb\",\n  ORACLESQL: \"oraclesql\",\n  GENERIC: \"generic\",\n};\n\nexport const IMPORT_FROM = {\n  JSON: 0,\n  DBML: 1,\n};\n"
  },
  {
    "path": "src/data/databases.js",
    "content": "import mysqlImage from \"../assets/mysql-icon.png\";\nimport postgresImage from \"../assets/postgres-icon.png\";\nimport sqliteImage from \"../assets/sqlite-icon.png\";\nimport mariadbImage from \"../assets/mariadb-icon.png\";\nimport mssqlImage from \"../assets/mssql-icon.png\";\nimport oraclesqlImage from \"../assets/oraclesql-icon.png\";\nimport i18n from \"../i18n/i18n\";\nimport { DB } from \"./constants\";\n\nexport const databases = new Proxy(\n  {\n    [DB.MYSQL]: {\n      name: \"MySQL\",\n      label: DB.MYSQL,\n      image: mysqlImage,\n      hasTypes: false,\n      hasUnsignedTypes: true,\n    },\n    [DB.POSTGRES]: {\n      name: \"PostgreSQL\",\n      label: DB.POSTGRES,\n      image: postgresImage,\n      hasTypes: true,\n      hasEnums: true,\n      hasArrays: true,\n    },\n    [DB.SQLITE]: {\n      name: \"SQLite\",\n      label: DB.SQLITE,\n      image: sqliteImage,\n      hasTypes: false,\n    },\n    [DB.MARIADB]: {\n      name: \"MariaDB\",\n      label: DB.MARIADB,\n      image: mariadbImage,\n      hasTypes: false,\n      hasUnsignedTypes: true,\n    },\n    [DB.MSSQL]: {\n      name: \"MSSQL\",\n      label: DB.MSSQL,\n      image: mssqlImage,\n      hasTypes: false,\n    },\n    [DB.ORACLESQL]: {\n      name: \"Oracle SQL\",\n      label: DB.ORACLESQL,\n      image: oraclesqlImage,\n      hasTypes: false,\n      hasEnums: false,\n      hasArrays: false,\n      beta: true,\n    },\n    [DB.GENERIC]: {\n      name: i18n.t(\"generic\"),\n      label: DB.GENERIC,\n      image: null,\n      description: i18n.t(\"generic_description\"),\n      hasTypes: true,\n    },\n  },\n  { get: (target, prop) => (prop in target ? target[prop] : {}) },\n);\n"
  },
  {
    "path": "src/data/datatypes.js",
    "content": "import { strHasQuotes } from \"../utils/utils\";\nimport {\n  binaryColor,\n  booleanColor,\n  dateColor,\n  decimalColor,\n  documentColor,\n  enumSetColor,\n  geometricColor,\n  intColor,\n  networkIdColor,\n  otherColor,\n  stringColor,\n  vectorColor,\n} from \"./constants\";\nimport { DB } from \"./constants\";\n\nconst intRegex = /^-?\\d*$/;\nconst doubleRegex = /^-?\\d*.?\\d+$/;\nconst binaryRegex = /^[01]+$/;\n\n/* eslint-disable no-unused-vars */\nconst defaultTypesBase = {\n  INT: {\n    type: \"INT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n  },\n  SMALLINT: {\n    type: \"SMALLINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n  },\n  BIGINT: {\n    type: \"BIGINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    isSized: false,\n    hasCheck: true,\n    hasPrecision: false,\n    canIncrement: true,\n  },\n  DECIMAL: {\n    type: \"DECIMAL\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  NUMERIC: {\n    type: \"NUMERIC\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  NUMBER: {\n    type: \"NUMBER\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return /^-?\\d+(\\.\\d+)?$/.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n    canIncrement: false,\n  },\n  FLOAT: {\n    type: \"FLOAT\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  DOUBLE: {\n    type: \"DOUBLE\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  REAL: {\n    type: \"REAL\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n  },\n  CHAR: {\n    type: \"CHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: true,\n  },\n  VARCHAR: {\n    type: \"VARCHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  VARCHAR2: {\n    type: \"VARCHAR2\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 225,\n    hasQuotes: true,\n  },\n  TEXT: {\n    type: \"TEXT\",\n    color: stringColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 65535,\n    hasQuotes: true,\n  },\n  TIME: {\n    type: \"TIME\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^(?:[01]?\\d|2[0-3]):[0-5]?\\d:[0-5]?\\d$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TIMESTAMP: {\n    type: \"TIMESTAMP\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (!/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/.test(field.default)) {\n        return false;\n      }\n      const content = field.default.split(\" \");\n      const date = content[0].split(\"-\");\n      return (\n        Number.parseInt(date[0]) >= 1970 && Number.parseInt(date[0]) <= 2038\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  DATE: {\n    type: \"DATE\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^\\d{4}-\\d{2}-\\d{2}$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  DATETIME: {\n    type: \"DATETIME\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (!/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/.test(field.default)) {\n        return false;\n      }\n      const c = field.default.split(\" \");\n      const d = c[0].split(\"-\");\n      return Number.parseInt(d[0]) >= 1000 && Number.parseInt(d[0]) <= 9999;\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  BOOLEAN: {\n    type: \"BOOLEAN\",\n    color: booleanColor,\n    checkDefault: (field) => {\n      return (\n        field.default.toLowerCase() === \"false\" ||\n        field.default.toLowerCase() === \"true\" ||\n        field.default === \"0\" ||\n        field.default === \"1\"\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n  },\n  BINARY: {\n    type: \"BINARY\",\n    color: binaryColor,\n    checkDefault: (field) => {\n      return (\n        field.default.length <= field.size && binaryRegex.test(field.default)\n      );\n    },\n    hasCheck: false,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: true,\n  },\n  VARBINARY: {\n    type: \"VARBINARY\",\n    color: binaryColor,\n    checkDefault: (field) => {\n      return (\n        field.default.length <= field.size && binaryRegex.test(field.default)\n      );\n    },\n    hasCheck: false,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  BLOB: {\n    type: \"BLOB\",\n    color: binaryColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  CLOB: {\n    type: \"CLOB\",\n    color: stringColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  NCLOB: {\n    type: \"NCLOB\",\n    color: stringColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  JSON: {\n    type: \"JSON\",\n    color: documentColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  UUID: {\n    type: \"UUID\",\n    color: networkIdColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: false,\n  },\n  ENUM: {\n    type: \"ENUM\",\n    color: enumSetColor,\n    checkDefault: (field) => {\n      return field.values.includes(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  SET: {\n    type: \"SET\",\n    color: enumSetColor,\n    checkDefault: (field) => {\n      const defaultValues = field.default.split(\",\");\n      for (let i = 0; i < defaultValues.length; i++) {\n        if (!field.values.includes(defaultValues[i].trim())) return false;\n      }\n      return true;\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n};\n\nexport const defaultTypes = new Proxy(defaultTypesBase, {\n  get: (target, prop) => (prop in target ? target[prop] : false),\n});\n\nconst mysqlTypesBase = {\n  TINYINT: {\n    type: \"TINYINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n    signed: true,\n  },\n  SMALLINT: {\n    type: \"SMALLINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n    signed: true,\n  },\n  MEDIUMINT: {\n    type: \"MEDIUMINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n    signed: true,\n  },\n  INTEGER: {\n    type: \"INTEGER\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n    signed: true,\n  },\n  BIGINT: {\n    type: \"BIGINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n    signed: true,\n  },\n  DECIMAL: {\n    type: \"DECIMAL\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  NUMERIC: {\n    type: \"NUMERIC\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  FLOAT: {\n    type: \"FLOAT\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  DOUBLE: {\n    type: \"DOUBLE\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  BIT: {\n    type: \"BIT\",\n    color: binaryColor,\n    checkDefault: (field) => {\n      return field.default === \"1\" || field.default === \"0\";\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  BOOLEAN: {\n    type: \"BOOLEAN\",\n    color: booleanColor,\n    checkDefault: (field) => {\n      return (\n        field.default.toLowerCase() === \"false\" ||\n        field.default.toLowerCase() === \"true\" ||\n        field.default === \"0\" ||\n        field.default === \"1\"\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n  },\n  TIME: {\n    type: \"TIME\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^(?:[01]?\\d|2[0-3]):[0-5]?\\d:[0-5]?\\d$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TIMESTAMP: {\n    type: \"TIMESTAMP\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (!/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/.test(field.default)) {\n        return false;\n      }\n      const content = field.default.split(\" \");\n      const date = content[0].split(\"-\");\n      return (\n        Number.parseInt(date[0]) >= 1970 && Number.parseInt(date[0]) <= 2038\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  DATE: {\n    type: \"DATE\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^\\d{4}-\\d{2}-\\d{2}$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  DATETIME: {\n    type: \"DATETIME\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (!/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/.test(field.default)) {\n        return false;\n      }\n      const c = field.default.split(\" \");\n      const d = c[0].split(\"-\");\n      return Number.parseInt(d[0]) >= 1000 && Number.parseInt(d[0]) <= 9999;\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  YEAR: {\n    type: \"YEAR\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^\\d{4}$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n  },\n  CHAR: {\n    type: \"CHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: true,\n  },\n  VARCHAR: {\n    type: \"VARCHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  BINARY: {\n    type: \"BINARY\",\n    color: binaryColor,\n    checkDefault: (field) => {\n      return (\n        field.default.length <= field.size && binaryRegex.test(field.default)\n      );\n    },\n    hasCheck: false,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: true,\n  },\n  VARBINARY: {\n    type: \"VARBINARY\",\n    color: binaryColor,\n    checkDefault: (field) => {\n      return (\n        field.default.length <= field.size && binaryRegex.test(field.default)\n      );\n    },\n    hasCheck: false,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  TINYBLOB: {\n    type: \"TINYBLOB\",\n    color: binaryColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  BLOB: {\n    type: \"BLOB\",\n    color: binaryColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  MEDIUMBLOB: {\n    type: \"MEDIUMBLOB\",\n    color: binaryColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  LONGBLOB: {\n    type: \"LONGBLOB\",\n    color: binaryColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  TINYTEXT: {\n    type: \"TINYTEXT\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 65535,\n    hasQuotes: true,\n  },\n  TEXT: {\n    type: \"TEXT\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 65535,\n    hasQuotes: true,\n  },\n  MEDIUMTEXT: {\n    type: \"MEDIUMTEXT\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 65535,\n    hasQuotes: true,\n  },\n  LONGTEXT: {\n    type: \"LONGTEXT\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 65535,\n    hasQuotes: true,\n  },\n  ENUM: {\n    type: \"ENUM\",\n    color: enumSetColor,\n    checkDefault: (field) => {\n      return field.values.includes(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  SET: {\n    type: \"SET\",\n    color: enumSetColor,\n    checkDefault: (field) => {\n      const defaultValues = field.default.split(\",\");\n      for (let i = 0; i < defaultValues.length; i++) {\n        if (!field.values.includes(defaultValues[i].trim())) return false;\n      }\n      return true;\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  GEOMETRY: {\n    type: \"GEOMETRY\",\n    color: geometricColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  POINT: {\n    type: \"POINT\",\n    color: geometricColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  LINESTRING: {\n    type: \"LINESTRING\",\n    color: geometricColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  POLYGON: {\n    type: \"POLYGON\",\n    color: geometricColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  MULTIPOINT: {\n    type: \"MULTIPOINT\",\n    color: geometricColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  MULTILINESTRING: {\n    type: \"MULTILINESTRING\",\n    color: geometricColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  MULTIPOLYGON: {\n    type: \"MULTIPOLYGON\",\n    color: geometricColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  GEOMETRYCOLLECTION: {\n    type: \"GEOMETRYCOLLECTION\",\n    color: geometricColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  JSON: {\n    type: \"JSON\",\n    color: documentColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n};\n\nexport const mysqlTypes = new Proxy(mysqlTypesBase, {\n  get: (target, prop) => (prop in target ? target[prop] : false),\n});\n\nconst postgresTypesBase = {\n  SMALLINT: {\n    type: \"SMALLINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n    compatibleWith: [\"SMALLSERIAL\", \"SERIAL\", \"BIGSERIAL\", \"INTEGER\", \"BIGINT\"],\n  },\n  INTEGER: {\n    type: \"INTEGER\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n    compatibleWith: [\n      \"SMALLSERIAL\",\n      \"SERIAL\",\n      \"BIGSERIAL\",\n      \"SMALLINT\",\n      \"BIGINT\",\n    ],\n  },\n  BIGINT: {\n    type: \"BIGINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n    compatibleWith: [\n      \"SMALLSERIAL\",\n      \"SERIAL\",\n      \"BIGSERIAL\",\n      \"INTEGER\",\n      \"SMALLINT\",\n    ],\n  },\n  DECIMAL: {\n    type: \"DECIMAL\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  NUMERIC: {\n    type: \"NUMERIC\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  REAL: {\n    type: \"REAL\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  \"DOUBLE PRECISION\": {\n    type: \"DOUBLE PRECISION\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  SMALLSERIAL: {\n    type: \"SMALLSERIAL\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    compatibleWith: [\"INTEGER\", \"SERIAL\", \"BIGSERIAL\", \"SMALLINT\", \"BIGINT\"],\n  },\n  SERIAL: {\n    type: \"SERIAL\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    compatibleWith: [\n      \"INTEGER\",\n      \"SMALLSERIAL\",\n      \"BIGSERIAL\",\n      \"SMALLINT\",\n      \"BIGINT\",\n    ],\n  },\n  BIGSERIAL: {\n    type: \"BIGSERIAL\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    compatibleWith: [\"INTEGER\", \"SERIAL\", \"SMALLSERIAL\", \"SMALLINT\", \"BIGINT\"],\n  },\n  MONEY: {\n    type: \"MONEY\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  CHAR: {\n    type: \"CHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: true,\n  },\n  VARCHAR: {\n    type: \"VARCHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  TEXT: {\n    type: \"TEXT\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  BYTEA: {\n    type: \"BYTEA\",\n    color: binaryColor,\n    checkDefault: (field) => {\n      return /^[0-9a-fA-F]*$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    defaultSize: null,\n    hasQuotes: true,\n  },\n  DATE: {\n    type: \"DATE\",\n    color: dateColor,\n    checkDefault: (field) => {\n      const specialValues = [\n        \"epoch\",\n        \"infinity\",\n        \"-infinity\",\n        \"now\",\n        \"today\",\n        \"tomorrow\",\n        \"yesterday\",\n        \"current_date\",\n        \"current_timestamp\",\n        \"current_time\",\n      ];\n      return (\n        /^\\d{4}-\\d{2}-\\d{2}$/.test(field.default) ||\n        specialValues.includes(field.default.toLowerCase())\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TIME: {\n    type: \"TIME\",\n    color: dateColor,\n    checkDefault: (field) => {\n      const specialValues = [\"now\", \"allballs\"];\n      return (\n        /^(?:[01]?\\d|2[0-3]):[0-5]?\\d:[0-5]?\\d$/.test(field.default) ||\n        specialValues.includes(field.default.toLowerCase())\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TIMETZ: {\n    type: \"TIMETZ\",\n    color: dateColor,\n    checkDefault: (field) => {\n      const specialValues = [\"now\", \"allballs\"];\n      return (\n        /^(?:[01]?\\d|2[0-3]):[0-5]?\\d:[0-5]?\\d([+-]\\d{2}:\\d{2})?$/.test(\n          field.default,\n        ) || specialValues.includes(field.default.toLowerCase())\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TIMESTAMP: {\n    type: \"TIMESTAMP\",\n    color: dateColor,\n    checkDefault: (field) => {\n      const content = field.default.split(\" \");\n      const date = content[0].split(\"-\");\n      const specialValues = [\n        \"epoch\",\n        \"infinity\",\n        \"-infinity\",\n        \"now\",\n        \"today\",\n        \"tomorrow\",\n        \"yesterday\",\n        \"current_timestamp\",\n      ];\n      return (\n        /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/.test(field.default) ||\n        (Number.parseInt(date[0]) >= 1970 &&\n          Number.parseInt(date[0]) <= 2038) ||\n        specialValues.includes(field.default.toLowerCase())\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TIMESTAMPTZ: {\n    type: \"TIMESTAMPTZ\",\n    color: dateColor,\n    checkDefault: (field) => {\n      const specialValues = [\n        \"epoch\",\n        \"infinity\",\n        \"-infinity\",\n        \"now\",\n        \"today\",\n        \"tomorrow\",\n        \"yesterday\",\n        \"current_timestamp\",\n      ];\n      return (\n        /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}([+-]\\d{2}:\\d{2})?$/.test(\n          field.default,\n        ) || specialValues.includes(field.default.toLowerCase())\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  INTERVAL: {\n    type: \"INTERVAL\",\n    color: dateColor,\n    checkDefault: (field) => /^['\"\\d\\s\\\\-]+$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  BOOLEAN: {\n    type: \"BOOLEAN\",\n    color: booleanColor,\n    checkDefault: (field) => /^(true|false)$/i.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: false,\n  },\n  POINT: {\n    type: \"POINT\",\n    color: geometricColor,\n    checkDefault: (field) => /^\\(\\d+,\\d+\\)$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: false,\n  },\n  LINE: {\n    type: \"LINE\",\n    color: geometricColor,\n    checkDefault: (field) => /^(\\(\\d+,\\d+\\),)+\\(\\d+,\\d+\\)$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: false,\n  },\n  LSEG: {\n    type: \"LSEG\",\n    color: geometricColor,\n    checkDefault: (field) => /^(\\(\\d+,\\d+\\),)+\\(\\d+,\\d+\\)$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: false,\n  },\n  BOX: {\n    type: \"BOX\",\n    color: geometricColor,\n    checkDefault: (field) =>\n      /^\\(\\d+(\\.\\d+)?,\\d+(\\.\\d+)?\\),\\(\\d+(\\.\\d+)?,\\d+(\\.\\d+)?\\)$/.test(\n        field.default,\n      ),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  PATH: {\n    type: \"PATH\",\n    color: geometricColor,\n    checkDefault: (field) =>\n      /^\\((\\d+(\\.\\d+)?,\\d+(\\.\\d+)?(,\\d+(\\.\\d+)?,\\d+(\\.\\d+)?)*?)\\)$/.test(\n        field.default,\n      ),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  POLYGON: {\n    type: \"POLYGON\",\n    color: geometricColor,\n    checkDefault: (field) =>\n      /^\\((\\d+(\\.\\d+)?,\\d+(\\.\\d+)?(,\\d+(\\.\\d+)?,\\d+(\\.\\d+)?)*?)\\)$/.test(\n        field.default,\n      ),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  CIRCLE: {\n    type: \"CIRCLE\",\n    color: geometricColor,\n    checkDefault: (field) =>\n      /^<\\(\\d+(\\.\\d+)?,\\d+(\\.\\d+)?\\),\\d+(\\.\\d+)?\\\\>$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  CIDR: {\n    type: \"CIDR\",\n    color: networkIdColor,\n    checkDefault: (field) =>\n      /^(\\d{1,3}\\.){3}\\d{1,3}\\/\\d{1,2}$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  INET: {\n    type: \"INET\",\n    color: networkIdColor,\n    checkDefault: (field) =>\n      /^(\\d{1,3}\\.){3}\\d{1,3}(\\/\\d{1,2})?$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  MACADDR: {\n    type: \"MACADDR\",\n    color: networkIdColor,\n    checkDefault: (field) =>\n      /^([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  MACADDR8: {\n    type: \"MACADDR8\",\n    color: networkIdColor,\n    checkDefault: (field) =>\n      /^([A-Fa-f0-9]{2}:){7}[A-Fa-f0-9]{2}$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  BIT: {\n    type: \"BIT\",\n    color: binaryColor,\n    checkDefault: (field) => /^[01]{1,}$/.test(field.default),\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: false,\n  },\n  VARBIT: {\n    type: \"VARBIT\",\n    color: binaryColor,\n    checkDefault: (field) => /^[01]*$/.test(field.default),\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: false,\n  },\n  VECTOR: {\n    type: \"VECTOR\",\n    color: vectorColor,\n    checkDefault: (field) => {\n      let elements;\n      let elementsStr = field.default;\n      try {\n        if (strHasQuotes(field.default)) {\n          elementsStr = field.default.slice(1, -1);\n        }\n        elements = JSON.parse(elementsStr);\n        return (\n          Array.isArray(elements) &&\n          elements.length === field.size &&\n          elements.every(Number.isFinite)\n        );\n      } catch (e) {\n        return false;\n      }\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  HALFVEC: {\n    type: \"HALFVEC\",\n    color: vectorColor,\n    checkDefault: (field) => {\n      let elements;\n      let elementsStr = field.default;\n      try {\n        if (strHasQuotes(field.default)) {\n          elementsStr = field.default.slice(1, -1);\n        }\n        elements = JSON.parse(elementsStr);\n        return (\n          Array.isArray(elements) &&\n          elements.length === field.size &&\n          elements.every(Number.isFinite)\n        );\n      } catch (e) {\n        return false;\n      }\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  SPARSEVEC: {\n    type: \"SPARSEVEC\",\n    color: vectorColor,\n    checkDefault: (field) => {\n      let elementsStr = field.default;\n      if (strHasQuotes(field.default)) {\n        elementsStr = field.default.slice(1, -1);\n      }\n      const lengthStr = elementsStr.split(\"/\")[1];\n      const length = Number.parseInt(lengthStr);\n      return length === field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TSVECTOR: {\n    type: \"TSVECTOR\",\n    color: otherColor,\n    checkDefault: (field) => /^[A-Za-z0-9: ]*$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: false,\n  },\n  TSQUERY: {\n    type: \"TSQUERY\",\n    color: otherColor,\n    checkDefault: (field) => /^[A-Za-z0-9: &|!()]*$/.test(field.default),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: false,\n  },\n  JSON: {\n    type: \"JSON\",\n    color: documentColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n    noDefault: true,\n  },\n  JSONB: {\n    type: \"JSONB\",\n    color: documentColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n    noDefault: true,\n  },\n  UUID: {\n    type: \"UUID\",\n    color: networkIdColor,\n    checkDefault: (field) =>\n      /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(\n        field.default,\n      ),\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n    noDefault: false,\n  },\n  XML: {\n    type: \"XML\",\n    color: documentColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n    noDefault: true,\n  },\n};\n\nexport const postgresTypes = new Proxy(postgresTypesBase, {\n  get: (target, prop) => (prop in target ? target[prop] : false),\n});\n\nconst sqliteTypesBase = {\n  INTEGER: {\n    type: \"INTEGER\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n  },\n  REAL: {\n    type: \"REAL\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  NUMERIC: {\n    type: \"NUMERIC\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  BOOLEAN: {\n    type: \"BOOLEAN\",\n    color: booleanColor,\n    checkDefault: (field) => {\n      return (\n        field.default.toLowerCase() === \"false\" ||\n        field.default.toLowerCase() === \"true\" ||\n        field.default === \"0\" ||\n        field.default === \"1\"\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n  },\n  VARCHAR: {\n    type: \"VARCHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  TEXT: {\n    type: \"TEXT\",\n    color: stringColor,\n    checkDefault: (field) => true,\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 65535,\n    hasQuotes: true,\n  },\n  BLOB: {\n    type: \"BLOB\",\n    color: binaryColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  TIME: {\n    type: \"TIME\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^(?:[01]?\\d|2[0-3]):[0-5]?\\d:[0-5]?\\d$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TIMESTAMP: {\n    type: \"TIMESTAMP\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (!/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/.test(field.default)) {\n        return false;\n      }\n      const content = field.default.split(\" \");\n      const date = content[0].split(\"-\");\n      return (\n        Number.parseInt(date[0]) >= 1970 && Number.parseInt(date[0]) <= 2038\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  DATE: {\n    type: \"DATE\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^\\d{4}-\\d{2}-\\d{2}$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  DATETIME: {\n    type: \"DATETIME\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (!/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/.test(field.default)) {\n        return false;\n      }\n      const c = field.default.split(\" \");\n      const d = c[0].split(\"-\");\n      return Number.parseInt(d[0]) >= 1000 && Number.parseInt(d[0]) <= 9999;\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n};\n\nexport const sqliteTypes = new Proxy(sqliteTypesBase, {\n  get: (target, prop) => (prop in target ? target[prop] : false),\n});\n\nconst mssqlTypesBase = {\n  TINYINT: {\n    type: \"TINYINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n  },\n  SMALLINT: {\n    type: \"SMALLINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n  },\n  INTEGER: {\n    type: \"INTEGER\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n  },\n  BIGINT: {\n    type: \"BIGINT\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n  },\n  BIT: {\n    type: \"BIT\",\n    color: binaryColor,\n    checkDefault: (field) => {\n      return field.default === \"1\" || field.default === \"0\";\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  DECIMAL: {\n    type: \"DECIMAL\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  NUMERIC: {\n    type: \"NUMERIC\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  FLOAT: {\n    type: \"FLOAT\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  DOUBLE: {\n    type: \"DOUBLE\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  REAL: {\n    type: \"REAL\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n  },\n  MONEY: {\n    type: \"MONEY\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  SMALLMONEY: {\n    type: \"MONEY\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return doubleRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  DATE: {\n    type: \"DATE\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^\\d{4}-\\d{2}-\\d{2}$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  DATETIME: {\n    type: \"DATETIME\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (!/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/.test(field.default)) {\n        return false;\n      }\n      const c = field.default.split(\" \");\n      const d = c[0].split(\"-\");\n      return Number.parseInt(d[0]) >= 1000 && Number.parseInt(d[0]) <= 9999;\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  DATETIME2: {\n    type: \"DATETIME2\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (!/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/.test(field.default)) {\n        return false;\n      }\n      const c = field.default.split(\" \");\n      const d = c[0].split(\"-\");\n      return Number.parseInt(d[0]) >= 1000 && Number.parseInt(d[0]) <= 9999;\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: true,\n    hasQuotes: true,\n  },\n  DATETIMEOFFSET: {\n    type: \"DATETIMEOFFSET\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (\n        !/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?([+-]\\d{2}:\\d{2})?$/.test(\n          field.default,\n        )\n      ) {\n        return false;\n      }\n      const c = field.default.split(\" \");\n      const d = c[0].split(\"-\");\n      return Number.parseInt(d[0]) >= 1000 && Number.parseInt(d[0]) <= 9999;\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: true,\n    hasQuotes: true,\n  },\n  SMALLDATETIME: {\n    type: \"SMALLDATETIME\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (!/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}(:\\d{2})?$/.test(field.default)) {\n        return false;\n      }\n      const c = field.default.split(\" \");\n      const d = c[0].split(\"-\");\n      return Number.parseInt(d[0]) >= 1900 && Number.parseInt(d[0]) <= 2079;\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TIME: {\n    type: \"TIME\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^(?:[01]?\\d|2[0-3]):[0-5]?\\d:[0-5]?\\d$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TIMESTAMP: {\n    type: \"TIMESTAMP\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      if (!/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/.test(field.default)) {\n        return false;\n      }\n      const content = field.default.split(\" \");\n      const date = content[0].split(\"-\");\n      return (\n        Number.parseInt(date[0]) >= 1970 && Number.parseInt(date[0]) <= 2038\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  CHAR: {\n    type: \"CHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: true,\n  },\n  VARCHAR: {\n    type: \"VARCHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  TEXT: {\n    type: \"TEXT\",\n    color: stringColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 65535,\n    hasQuotes: true,\n  },\n  NCHAR: {\n    type: \"CHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: true,\n  },\n  NVARCHAR: {\n    type: \"VARCHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  NTEXT: {\n    type: \"TEXT\",\n    color: stringColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 65535,\n    hasQuotes: true,\n  },\n  BINARY: {\n    type: \"BINARY\",\n    color: binaryColor,\n    checkDefault: (field) => {\n      return (\n        field.default.length <= field.size && binaryRegex.test(field.default)\n      );\n    },\n    hasCheck: false,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: true,\n  },\n  VARBINARY: {\n    type: \"VARBINARY\",\n    color: binaryColor,\n    checkDefault: (field) => {\n      return (\n        field.default.length <= field.size && binaryRegex.test(field.default)\n      );\n    },\n    hasCheck: false,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  IMAGE: {\n    type: \"IMAGE\",\n    color: binaryColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n    noDefault: true,\n  },\n  UNIQUEIDENTIFIER: {\n    type: \"UNIQUEIDENTIFIER\",\n    color: networkIdColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  XML: {\n    type: \"XML\",\n    color: documentColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n    noDefault: true,\n  },\n  CURSOR: {\n    type: \"CURSOR\",\n    color: otherColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: false,\n    noDefault: true,\n  },\n  SQL_VARIANT: {\n    type: \"SQL_VARIANT\",\n    color: otherColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: false,\n    noDefault: true,\n  },\n  JSON: {\n    type: \"JSON\",\n    color: documentColor,\n    checkDefault: (field) => true,\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n    noDefault: true,\n  },\n};\n\nexport const mssqlTypes = new Proxy(mssqlTypesBase, {\n  get: (target, prop) => (prop in target ? target[prop] : false),\n});\n\nconst oraclesqlTypesBase = {\n  INTEGER: {\n    type: \"INTEGER\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n  },\n  NUMBER: {\n    type: \"NUMBER\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return /^-?\\d+(\\.\\d+)?$/.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n    canIncrement: false,\n  },\n  FLOAT: {\n    type: \"FLOAT\",\n    color: decimalColor,\n    checkDefault: (field) => {\n      return /^-?\\d+(\\.\\d+)?$/.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: true,\n  },\n  LONG: {\n    type: \"LONG\",\n    color: intColor,\n    checkDefault: (field) => {\n      return intRegex.test(field.default);\n    },\n    hasCheck: true,\n    isSized: false,\n    hasPrecision: false,\n    canIncrement: true,\n  },\n  VARCHAR2: {\n    type: \"VARCHAR2\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  NVARCHAR2: {\n    type: \"VARCHAR2\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: true,\n  },\n  CHAR: {\n    type: \"CHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: true,\n  },\n  NCHAR: {\n    type: \"NCHAR\",\n    color: stringColor,\n    checkDefault: (field) => {\n      if (strHasQuotes(field.default)) {\n        return field.default.length - 2 <= field.size;\n      }\n      return field.default.length <= field.size;\n    },\n    hasCheck: true,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 1,\n    hasQuotes: true,\n  },\n  CLOB: {\n    type: \"CLOB\",\n    color: stringColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  NCLOB: {\n    type: \"NCLOB\",\n    color: stringColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  BLOB: {\n    type: \"BLOB\",\n    color: binaryColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  BFILE: {\n    type: \"BFILE\",\n    color: otherColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  JSON: {\n    type: \"JSON\",\n    color: documentColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  VECTOR: {\n    type: \"VECTOR\",\n    color: vectorColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: false,\n    hasPrecision: false,\n    noDefault: true,\n  },\n  DATE: {\n    type: \"DATE\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^\\d{4}-\\d{2}-\\d{2}$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  TIMESTAMP: {\n    type: \"TIMESTAMP\",\n    color: dateColor,\n    checkDefault: (field) => {\n      if (field.default.toUpperCase() === \"CURRENT_TIMESTAMP\") {\n        return true;\n      }\n      return /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?$/.test(\n        field.default,\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: true,\n    hasQuotes: true,\n  },\n  INTERVAL: {\n    type: \"INTERVAL\",\n    color: dateColor,\n    checkDefault: (field) => {\n      return /^INTERVAL\\s'\\d+'(\\s+DAY|HOUR|MINUTE|SECOND)?$/.test(\n        field.default,\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n    hasQuotes: true,\n  },\n  BOOLEAN: {\n    type: \"BOOLEAN\",\n    color: booleanColor,\n    checkDefault: (field) => {\n      return (\n        field.default === \"0\" ||\n        field.default === \"1\" ||\n        field.default.toUpperCase() === \"TRUE\" ||\n        field.default.toUpperCase() === \"FALSE\"\n      );\n    },\n    hasCheck: false,\n    isSized: false,\n    hasPrecision: false,\n  },\n  RAW: {\n    type: \"RAW\",\n    color: binaryColor,\n    checkDefault: (field) => {\n      return /^[0-9A-Fa-f]+$/.test(field.default);\n    },\n    hasCheck: false,\n    isSized: true,\n    hasPrecision: false,\n    defaultSize: 255,\n    hasQuotes: false,\n  },\n};\n\nexport const oraclesqlTypes = new Proxy(oraclesqlTypesBase, {\n  get: (target, prop) => (prop in target ? target[prop] : false),\n});\n\nexport const mariadbTypesBase = {\n  UUID: {\n    type: \"UUID\",\n    color: networkIdColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: true,\n    hasPrecision: false,\n    noDefault: false,\n  },\n  INET4: {\n    type: \"INET4\",\n    color: networkIdColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: true,\n    hasPrecision: false,\n    noDefault: false,\n  },\n  INET6: {\n    type: \"INET6\",\n    color: networkIdColor,\n    checkDefault: (field) => true,\n    isSized: false,\n    hasCheck: true,\n    hasPrecision: false,\n    noDefault: false,\n  },\n};\n\nexport const mariadbTypes = new Proxy(\n  { ...mysqlTypes, ...mariadbTypesBase },\n  {\n    get: (target, prop) => (prop in target ? target[prop] : false),\n  },\n);\n\nconst dbToTypesBase = {\n  [DB.GENERIC]: defaultTypes,\n  [DB.MYSQL]: mysqlTypes,\n  [DB.POSTGRES]: postgresTypes,\n  [DB.SQLITE]: sqliteTypes,\n  [DB.MSSQL]: mssqlTypes,\n  [DB.MARIADB]: mariadbTypes,\n  [DB.ORACLESQL]: oraclesqlTypes,\n};\n\nexport const dbToTypes = new Proxy(dbToTypesBase, {\n  get: (target, prop) => (prop in target ? target[prop] : false),\n});\n"
  },
  {
    "path": "src/data/db.js",
    "content": "import Dexie from \"dexie\";\nimport { templateSeeds } from \"./seeds\";\n\nexport const db = new Dexie(\"drawDB\");\n\ndb.version(67)\n  .stores({\n    diagrams: \"++id, lastModified, loadedFromGistId, diagramId\",\n    templates: \"++id, custom, templateId\",\n  })\n  .upgrade(async (tx) => {\n    await tx.diagrams.toCollection().modify((diagram) => {\n      if (!diagram.diagramId) {\n        diagram.diagramId = crypto.randomUUID();\n      }\n    });\n    await tx.templates.toCollection().modify((template) => {\n      if (!template.templateId) {\n        template.templateId = crypto.randomUUID();\n      }\n    });\n  });\n\ndb.on(\"populate\", (transaction) => {\n  transaction.templates.bulkAdd(templateSeeds).catch((e) => console.log(e));\n});\n"
  },
  {
    "path": "src/data/editorConfig.js",
    "content": "import { HeadingNode, QuoteNode } from \"@lexical/rich-text\";\nimport { TableCellNode, TableNode, TableRowNode } from \"@lexical/table\";\nimport { ListItemNode, ListNode } from \"@lexical/list\";\nimport { CodeHighlightNode, CodeNode } from \"@lexical/code\";\nimport { AutoLinkNode, LinkNode } from \"@lexical/link\";\n\nconst exampleTheme = {\n  ltr: \"ltr\",\n  rtl: \"rtl\",\n  placeholder: \"editor-placeholder\",\n  paragraph: \"editor-paragraph\",\n  quote: \"editor-quote\",\n  heading: {\n    h1: \"editor-heading-h1\",\n    h2: \"editor-heading-h2\",\n    h3: \"editor-heading-h3\",\n    h4: \"editor-heading-h4\",\n    h5: \"editor-heading-h5\",\n  },\n  list: {\n    nested: {\n      listitem: \"editor-nested-listitem\",\n    },\n    ol: \"editor-list-ol\",\n    ul: \"editor-list-ul\",\n    listitem: \"editor-listitem\",\n  },\n  image: \"editor-image\",\n  link: \"editor-link\",\n  text: {\n    bold: \"editor-text-bold\",\n    italic: \"editor-text-italic\",\n    overflowed: \"editor-text-overflowed\",\n    hashtag: \"editor-text-hashtag\",\n    underline: \"editor-text-underline\",\n    strikethrough: \"editor-text-strikethrough\",\n    underlineStrikethrough: \"editor-text-underlineStrikethrough\",\n    code: \"editor-text-code\",\n  },\n  code: \"editor-code\",\n  codeHighlight: {\n    atrule: \"editor-tokenAttr\",\n    attr: \"editor-tokenAttr\",\n    boolean: \"editor-tokenProperty\",\n    builtin: \"editor-tokenSelector\",\n    cdata: \"editor-tokenComment\",\n    char: \"editor-tokenSelector\",\n    class: \"editor-tokenFunction\",\n    \"class-name\": \"editor-tokenFunction\",\n    comment: \"editor-tokenComment\",\n    constant: \"editor-tokenProperty\",\n    deleted: \"editor-tokenProperty\",\n    doctype: \"editor-tokenComment\",\n    entity: \"editor-tokenOperator\",\n    function: \"editor-tokenFunction\",\n    important: \"editor-tokenVariable\",\n    inserted: \"editor-tokenSelector\",\n    keyword: \"editor-tokenAttr\",\n    namespace: \"editor-tokenVariable\",\n    number: \"editor-tokenProperty\",\n    operator: \"editor-tokenOperator\",\n    prolog: \"editor-tokenComment\",\n    property: \"editor-tokenProperty\",\n    punctuation: \"editor-tokenPunctuation\",\n    regex: \"editor-tokenVariable\",\n    selector: \"editor-tokenSelector\",\n    string: \"editor-tokenSelector\",\n    symbol: \"editor-tokenProperty\",\n    tag: \"editor-tokenProperty\",\n    url: \"editor-tokenOperator\",\n    variable: \"editor-tokenVariable\",\n  },\n};\n\nexport const editorConfig = {\n  theme: exampleTheme,\n  onError(error) {\n    throw error;\n  },\n  nodes: [\n    HeadingNode,\n    ListNode,\n    ListItemNode,\n    QuoteNode,\n    CodeNode,\n    CodeHighlightNode,\n    TableNode,\n    TableCellNode,\n    TableRowNode,\n    AutoLinkNode,\n    LinkNode,\n  ],\n};\n"
  },
  {
    "path": "src/data/heroDiagram.js",
    "content": "import {\n  tableColorStripHeight,\n  tableFieldHeight,\n  tableHeaderHeight,\n} from \"./constants\";\n\nconst xOffset = window.innerWidth * 0.65;\nexport const diagram = {\n  tables: [\n    {\n      name: \"galactic_users\",\n      x: xOffset + 75,\n      y:\n        window.innerHeight * 0.23 -\n        (tableHeaderHeight + 4 * tableFieldHeight + tableColorStripHeight) *\n          0.5,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n        },\n        {\n          name: \"username\",\n          type: \"VARCHAR\",\n        },\n        {\n          name: \"email\",\n          type: \"VARCHAR\",\n        },\n        {\n          name: \"password\",\n          type: \"VARCHAR\",\n        },\n      ],\n      color: \"#7d9dff\",\n    },\n    {\n      id: 1,\n      name: \"celestial_data\",\n      x: xOffset + 27,\n      y:\n        window.innerHeight * 0.72 -\n        (tableHeaderHeight + 5 * tableFieldHeight + tableColorStripHeight) *\n          0.5,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n        },\n        {\n          name: \"user_id\",\n          type: \"INT\",\n        },\n        {\n          name: \"type\",\n          type: \"ENUM\",\n        },\n        {\n          name: \"time\",\n          type: \"TIMESTAMP\",\n        },\n        {\n          name: \"content\",\n          type: \"VARCHAR\",\n        },\n      ],\n      color: \"#89e667\",\n    },\n    {\n      id: 2,\n      name: \"astro_mine\",\n      x: xOffset + 336,\n      y:\n        window.innerHeight * 0.72 -\n        (tableHeaderHeight + 3 * tableFieldHeight + tableColorStripHeight) *\n          0.5,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n        },\n        {\n          name: \"asteroid_id\",\n          type: \"INT\",\n        },\n        {\n          name: \"data_id\",\n          type: \"INT\",\n        },\n      ],\n      color: \"#6360f7\",\n    },\n    {\n      id: 3,\n      name: \"asteroid\",\n      x: xOffset + 310,\n      y:\n        window.innerHeight * 0.23 -\n        (tableHeaderHeight + 3 * tableFieldHeight + tableColorStripHeight) *\n          0.5,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n        },\n        {\n          name: \"location\",\n          type: \"VARCHAR\",\n        },\n      ],\n      color: \"#3cde7d\",\n    },\n  ],\n  relationships: [\n    {\n      startTableId: 1,\n      startFieldId: 1,\n      endTableId: 0,\n      endFieldId: 0,\n      cardinality: \"many_to_one\",\n    },\n    {\n      startTableId: 2,\n      startFieldId: 2,\n      endTableId: 1,\n      endFieldId: 0,\n      cardinality: \"one_to_one\",\n    },\n    {\n      startTableId: 2,\n      startFieldId: 1,\n      endTableId: 3,\n      endFieldId: 0,\n      cardinality: \"many_to_one\",\n    },\n  ],\n};\n"
  },
  {
    "path": "src/data/schemas.js",
    "content": "export const tableSchema = {\n  type: \"object\",\n  properties: {\n    id: { type: [\"integer\", \"string\"] },\n    name: { type: \"string\" },\n    x: { type: \"number\" },\n    y: { type: \"number\" },\n    fields: {\n      type: \"array\",\n      items: {\n        type: \"object\",\n        properties: {\n          id: { type: [\"integer\", \"string\"] },\n          name: { type: \"string\" },\n          type: { type: \"string\" },\n          default: { type: [\"string\", \"number\", \"boolean\"] },\n          check: { type: \"string\" },\n          primary: { type: \"boolean\" },\n          unique: { type: \"boolean\" },\n          notNull: { type: \"boolean\" },\n          increment: { type: \"boolean\" },\n          comment: { type: \"string\" },\n          size: { type: [\"string\", \"number\"] },\n          values: { type: \"array\", items: { type: \"string\" } },\n        },\n        required: [\n          \"id\",\n          \"name\",\n          \"type\",\n          \"default\",\n          \"check\",\n          \"primary\",\n          \"unique\",\n          \"notNull\",\n          \"increment\",\n          \"comment\",\n        ],\n      },\n    },\n    comment: { type: \"string\" },\n    locked: { type: \"boolean\" },\n    hidden: { type: \"boolean\" },\n    indices: {\n      type: \"array\",\n      items: {\n        type: \"object\",\n        properties: {\n          name: { type: \"string\" },\n          unique: { type: \"boolean\" },\n          fields: {\n            type: \"array\",\n            items: { type: \"string\" },\n          },\n        },\n        required: [\"name\", \"unique\", \"fields\"],\n      },\n    },\n    color: { type: \"string\", pattern: \"^#[0-9a-fA-F]{6}$\" },\n    inherits: {\n      type: \"array\",\n      items: { type: [\"string\"] },\n    },\n  },\n  required: [\"id\", \"name\", \"x\", \"y\", \"fields\", \"comment\", \"indices\", \"color\"],\n};\n\nexport const areaSchema = {\n  type: \"object\",\n  properties: {\n    id: { type: \"integer\" },\n    name: { type: \"string\" },\n    x: { type: \"number\" },\n    y: { type: \"number\" },\n    width: { type: \"number\" },\n    height: { type: \"number\" },\n    locked: { type: \"boolean\" },\n    color: { type: \"string\", pattern: \"^#[0-9a-fA-F]{6}$\" },\n  },\n  required: [\"id\", \"name\", \"x\", \"y\", \"width\", \"height\", \"color\"],\n};\n\nexport const noteSchema = {\n  type: \"object\",\n  properties: {\n    id: { type: \"integer\" },\n    x: { type: \"number\" },\n    y: { type: \"number\" },\n    title: { type: \"string\" },\n    content: { type: \"string\" },\n    color: { type: \"string\", pattern: \"^#[0-9a-fA-F]{6}$\" },\n    height: { type: \"number\" },\n    locked: { type: \"boolean\" },\n  },\n  required: [\"id\", \"x\", \"y\", \"title\", \"content\", \"color\", \"height\"],\n};\n\nexport const typeSchema = {\n  type: \"object\",\n  properties: {\n    id: { type: [\"string\"] },\n    name: { type: \"string\" },\n    fields: {\n      type: \"array\",\n      items: {\n        type: \"object\",\n        properties: {\n          id: { type: [\"string\"] },\n          name: { type: \"string\" },\n          type: { type: \"string\" },\n          values: {\n            type: \"array\",\n            items: { type: \"string\" },\n          },\n        },\n        required: [\"name\", \"type\"],\n      },\n    },\n    comment: { type: \"string\" },\n  },\n  required: [\"name\", \"fields\", \"comment\"],\n};\n\nexport const enumSchema = {\n  type: \"object\",\n  properties: {\n    name: { type: \"string\" },\n    values: {\n      type: \"array\",\n      items: { type: \"string\" },\n    },\n  },\n};\n\nexport const jsonSchema = {\n  type: \"object\",\n  properties: {\n    tables: {\n      type: \"array\",\n      items: { ...tableSchema },\n    },\n    relationships: {\n      type: \"array\",\n      items: {\n        type: \"object\",\n        properties: {\n          startTableId: { type: [\"integer\", \"string\"] },\n          startFieldId: { type: [\"integer\", \"string\"] },\n          endTableId: { type: [\"integer\", \"string\"] },\n          endFieldId: { type: [\"integer\", \"string\"] },\n          name: { type: \"string\" },\n          cardinality: { type: \"string\" },\n          updateConstraint: { type: \"string\" },\n          deleteConstraint: { type: \"string\" },\n          id: { type: [\"integer\", \"string\"] },\n        },\n        required: [\n          \"startTableId\",\n          \"startFieldId\",\n          \"endTableId\",\n          \"endFieldId\",\n          \"name\",\n          \"cardinality\",\n          \"updateConstraint\",\n          \"deleteConstraint\",\n          \"id\",\n        ],\n      },\n    },\n    notes: {\n      type: \"array\",\n      items: { ...noteSchema },\n    },\n    subjectAreas: {\n      type: \"array\",\n      items: { ...areaSchema },\n    },\n    types: {\n      type: \"array\",\n      items: { ...typeSchema },\n    },\n    enums: {\n      type: \"array\",\n      items: { ...enumSchema },\n    },\n    title: { type: \"string\" },\n    database: { type: \"string\" },\n  },\n  required: [\"tables\", \"relationships\", \"notes\", \"subjectAreas\"],\n};\n\nexport const ddbSchema = {\n  type: \"object\",\n  properties: {\n    author: { type: \"string\" },\n    project: { type: \"string\" },\n    title: { type: \"string\" },\n    date: { type: \"string\" },\n    ...jsonSchema.properties,\n  },\n};\n"
  },
  {
    "path": "src/data/seeds.js",
    "content": "import { template1 } from \"../templates/template1\";\nimport { template2 } from \"../templates/template2\";\nimport { template3 } from \"../templates/template3\";\nimport { template4 } from \"../templates/template4\";\nimport { template5 } from \"../templates/template5\";\nimport { template6 } from \"../templates/template6\";\n\nconst templateSeeds = [\n  template1,\n  template2,\n  template3,\n  template4,\n  template5,\n  template6,\n];\n\nexport { templateSeeds };\n"
  },
  {
    "path": "src/data/socials.js",
    "content": "export const socials = {\n  docs: \"https://drawdb-io.github.io/docs\",\n  discord: \"https://discord.gg/BrjZgNrmR6\",\n  twitter: \"https://x.com/drawDB_\",\n  github: \"https://github.com/drawdb-io/drawdb\",\n};\n"
  },
  {
    "path": "src/data/surveyQuestions.js",
    "content": "export const questions = {\n  satisfaction: \"How satisfied are you with drawDB?\",\n  ease: \"How easy was it to get started with drawDB?\",\n  wouldRecommend: \"How likely are you to recommend drawDB?\",\n  hadDifficulty: \"Did you encounter any difficulties when navigating drawDB?\",\n  difficulty: \"What were the difficulties you faced?\",\n  triedOtherApps: \"Have you tried apps like drawDB?\",\n  comparison: \"How did you find drawDB as compared to other apps?\",\n  occupation: \"What is your occupation?\",\n};\n"
  },
  {
    "path": "src/hooks/index.js",
    "content": "export { default as useAreas } from \"./useAreas\";\nexport { default as useCanvas } from \"./useCanvas\";\nexport { default as useFullscreen } from \"./useFullscreen\";\nexport { default as useLayout } from \"./useLayout\";\nexport { default as useNotes } from \"./useNotes\";\nexport { default as useSaveState } from \"./useSaveState\";\nexport { default as useSelect } from \"./useSelect\";\nexport { default as useSettings } from \"./useSettings\";\nexport { default as useDiagram } from \"./useDiagram\";\nexport { default as useTransform } from \"./useTransform\";\nexport { default as useTypes } from \"./useTypes\";\nexport { default as useUndoRedo } from \"./useUndoRedo\";\nexport { default as useEnums } from \"./useEnums\";\nexport { default as useThemedPage } from \"./useThemedPage\";\n"
  },
  {
    "path": "src/hooks/useAreas.js",
    "content": "import { useContext } from \"react\";\nimport { AreasContext } from \"../context/AreasContext\";\n\nexport default function useAreas() {\n  return useContext(AreasContext);\n}\n"
  },
  {
    "path": "src/hooks/useCanvas.js",
    "content": "import { useContext } from \"react\";\nimport { CanvasContext } from \"../context/CanvasContext\";\n\nexport default function useCanvas() {\n  return useContext(CanvasContext);\n}\n"
  },
  {
    "path": "src/hooks/useDiagram.js",
    "content": "import { useContext } from \"react\";\nimport { DiagramContext } from \"../context/DiagramContext\";\n\nexport default function useDiagram() {\n  return useContext(DiagramContext);\n}\n"
  },
  {
    "path": "src/hooks/useEnums.js",
    "content": "import { useContext } from \"react\";\nimport { EnumsContext } from \"../context/EnumsContext\";\n\nexport default function useEnums() {\n  return useContext(EnumsContext);\n}\n"
  },
  {
    "path": "src/hooks/useFullscreen.js",
    "content": "import { useState } from \"react\";\nimport { useEventListener } from \"usehooks-ts\";\n\nexport default function useFullscreen() {\n  const [value, setValue] = useState(() => {\n    return document.fullscreenElement === document.documentElement;\n  });\n\n  function handleFullscreenChange() {\n    setValue(document.fullscreenElement === document.documentElement);\n  }\n\n  useEventListener(\"fullscreenchange\", handleFullscreenChange, document);\n\n  return value;\n}\n"
  },
  {
    "path": "src/hooks/useLayout.js",
    "content": "import { useContext } from \"react\";\nimport { LayoutContext } from \"../context/LayoutContext\";\n\nexport default function useLayout() {\n  return useContext(LayoutContext);\n}\n"
  },
  {
    "path": "src/hooks/useNotes.js",
    "content": "import { useContext } from \"react\";\nimport { NotesContext } from \"../context/NotesContext\";\n\nexport default function useNotes() {\n  return useContext(NotesContext);\n}\n"
  },
  {
    "path": "src/hooks/useSaveState.js",
    "content": "import { useContext } from \"react\";\nimport { SaveStateContext } from \"../context/SaveStateContext\";\n\nexport default function useSaveState() {\n  return useContext(SaveStateContext);\n}\n"
  },
  {
    "path": "src/hooks/useSelect.js",
    "content": "import { useContext } from \"react\";\nimport { SelectContext } from \"../context/SelectContext\";\n\nexport default function useSelect() {\n  return useContext(SelectContext);\n}\n"
  },
  {
    "path": "src/hooks/useSettings.js",
    "content": "import { useContext } from \"react\";\nimport { SettingsContext } from \"../context/SettingsContext\";\n\nexport default function useSettings() {\n  return useContext(SettingsContext);\n}\n"
  },
  {
    "path": "src/hooks/useThemedPage.js",
    "content": "import { useLayoutEffect } from \"react\";\nimport useSettings from \"./useSettings\";\n\n/**\n * Adds the `theme-mode` attribute to the body element for semi-ui dark theme\n */\nexport default function useThemedPage() {\n  const { settings } = useSettings();\n\n  useLayoutEffect(() => {\n    document.body.setAttribute(\"theme-mode\", settings.mode);\n  }, [settings]);\n}\n"
  },
  {
    "path": "src/hooks/useTransform.js",
    "content": "import { useContext } from \"react\";\nimport { TransformContext } from \"../context/TransformContext\";\n\nexport default function useTransform() {\n  return useContext(TransformContext);\n}\n"
  },
  {
    "path": "src/hooks/useTypes.js",
    "content": "import { useContext } from \"react\";\nimport { TypesContext } from \"../context/TypesContext\";\n\nexport default function useTypes() {\n  return useContext(TypesContext);\n}\n"
  },
  {
    "path": "src/hooks/useUndoRedo.js",
    "content": "import { useContext } from \"react\";\nimport { UndoRedoContext } from \"../context/UndoRedoContext\";\n\nexport default function useUndoRedo() {\n  return useContext(UndoRedoContext);\n}\n"
  },
  {
    "path": "src/i18n/i18n.js",
    "content": "import i18n from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\nimport LanguageDetector from \"i18next-browser-languagedetector\";\nimport { en, english } from \"./locales/en\";\nimport { zh, chinese } from \"./locales/zh\";\nimport { es, spanish } from \"./locales/es\";\nimport { da, danish } from \"./locales/da\";\nimport { de, german } from \"./locales/de\";\nimport { vi, vietnamese } from \"./locales/vi\";\nimport { pt, portuguese } from \"./locales/pt-br\";\nimport { fa, persian } from \"./locales/fa\";\nimport { hi, hindi } from \"./locales/hi\";\nimport { uk, ukrainian } from \"./locales/uk\";\nimport { ru, russian } from \"./locales/ru\";\nimport { el, greek } from \"./locales/el\";\nimport { ro, romanian } from \"./locales/ro\";\nimport { tr, turkish } from \"./locales/tr\";\nimport { mr, marathi } from \"./locales/mr\";\nimport { fr, french } from \"./locales/fr\";\nimport { he, hebrew } from \"./locales/he\";\nimport { pa, punjabi } from \"./locales/pa\";\nimport { hy, armenian } from \"./locales/hy\";\nimport { ar, arabic } from \"./locales/ar\";\nimport { zh_tw, traditionalChinese } from \"./locales/zh-tw\";\nimport { hu, hungarian } from \"./locales/hu\";\nimport { id, indonesian } from \"./locales/id\";\nimport { te, telugu } from \"./locales/te\";\nimport { tm, tamil } from \"./locales/tm\";\nimport { gu, gujarati } from \"./locales/gu\";\nimport { it, italian } from \"./locales/it\";\nimport { ko, korean } from \"./locales/ko\";\nimport { od, odia } from \"./locales/od\";\nimport { bn, bengali } from \"./locales/bn\";\nimport { ka, kannada } from \"./locales/ka\";\nimport { pl, polish } from \"./locales/pl\";\nimport { no, norwegian } from \"./locales/no\";\nimport { sv, swedish } from \"./locales/sv-se\";\nimport { ur, urdu } from \"./locales/ur\";\nimport { jp, japanese } from \"./locales/jp\";\nimport { ne, nepali } from \"./locales/ne\";\nimport { ug, uyghur } from \"./locales/ug\";\nimport { pa_pk, punjabipk } from \"./locales/pa-pk\";\nimport { cz, czech } from \"./locales/cz\";\nimport { ml, malayalam } from \"./locales/ml\";\nimport { nl, dutch } from \"./locales/nl\";\nimport { sd, sindhi } from \"./locales/sd\";\nimport { th, thai } from \"./locales/th\";\nimport { as, assamese } from \"./locales/as\";\nimport { bg, bulgarian } from \"./locales/bg\";\nimport { ms, malay } from \"./locales/ms\";\nimport { mn, mongolian } from \"./locales/mn\";\nimport { tl,filipino } from \"./locales/tl\";\nimport { sw, swahili } from \"./locales/sw\";\nimport { fi, finnish } from \"./locales/fi\";\n\n\nexport const languages = [\n  english,\n  bulgarian,\n  chinese,\n  danish,\n  spanish,\n  german,\n  vietnamese,\n  portuguese,\n  persian,\n  hindi,\n  assamese,\n  marathi,\n  greek,\n  ukrainian,\n  russian,\n  romanian,\n  turkish,\n  french,\n  punjabi,\n  armenian,\n  arabic,\n  traditionalChinese,\n  hebrew,\n  hungarian,\n  indonesian,\n  telugu,\n  tamil,\n  gujarati,\n  italian,\n  korean,\n  odia,\n  bengali,\n  kannada,\n  polish,\n  norwegian,\n  swedish,\n  urdu,\n  japanese,\n  nepali,\n  uyghur,\n  punjabipk,\n  czech,\n  malayalam,\n  dutch,\n  sindhi,\n  thai,\n  malay,\n  mongolian,\n  filipino,\n  swahili,\n  finnish,\n].sort((a, b) => a.name.localeCompare(b.name));\n\ni18n\n  .use(LanguageDetector)\n  .use(initReactI18next)\n  .init({\n    fallbackLng: \"en\",\n    debug: false,\n    interpolation: {\n      escapeValue: false,\n    },\n    resources: {\n      en,\n      zh,\n      es,\n      da,\n      de,\n      vi,\n      \"pt-BR\": pt,\n      fa,\n      hi,\n      mr,\n      uk,\n      ru,\n      el,\n      ro,\n      tr,\n      fr,\n      pa,\n      hy,\n      ar,\n      \"zh-TW\": zh_tw,\n      he,\n      hu,\n      id,\n      te,\n      tm,\n      gu,\n      it,\n      ko,\n      od,\n      bn,\n      ka,\n      pl,\n      no,\n      sv,\n      ur,\n      jp,\n      ne,\n      ug,\n      \"pa-PK\": pa_pk,\n      cz,\n      ml,\n      nl,\n      sd,\n      th,\n      as,\n      bg,\n      ms,\n      mn,\n      tl,\n      sw,\n      fi,\n    },\n  });\n\nexport default i18n;"
  },
  {
    "path": "src/i18n/locales/ar.js",
    "content": "const arabic = {\n  name: \"Arabic\",\n  native_name: \"العربية\",\n  code: \"ar\",\n};\n\nconst ar = {\n  translation: {\n    report_bug: \"الإبلاغ عن خطأ\",\n    import_from: \"استيراد\",\n    import: \"استيراد\",\n    file: \"ملف\",\n    new: \"جديد\",\n    new_window: \"نافذة جديدة\",\n    open: \"فتح\",\n    save: \"حفظ\",\n    save_as: \"حفظ باسم\",\n    save_as_template: \"حفظ كقالب\",\n    template_saved: \"تم حفظ القالب!\",\n    rename: \"إعادة تسمية\",\n    delete_diagram: \"حذف المخطط\",\n    are_you_sure_delete_diagram:\n      \"هل أنت متأكد أنك تريد حذف هذا المخطط؟ هذه العملية لا رجعة فيها.\",\n    oops_smth_went_wrong: \"عفوًا! حدث خطأ ما.\",\n    import_diagram: \"استيراد المخطط\",\n    import_from_source: \"استيراد من SQL\",\n    export_as: \"تصدير كـ\",\n    export_source: \"تصدير SQL\",\n    models: \"النماذج\",\n    exit: \"خروج\",\n    edit: \"تحرير\",\n    undo: \"تراجع\",\n    redo: \"إعادة\",\n    clear: \"مسح\",\n    are_you_sure_clear:\n      \"هل أنت متأكد أنك تريد مسح المخطط؟ هذه العملية لا رجعة فيها.\",\n    cut: \"قص\",\n    copy: \"نسخ\",\n    paste: \"لصق\",\n    duplicate: \"تكرار\",\n    delete: \"حذف\",\n    copy_as_image: \"نسخ كصورة\",\n    view: \"عرض\",\n    header: \"شريط القوائم\",\n    sidebar: \"الشريط الجانبي\",\n    issues: \"مشكلات\",\n    presentation_mode: \"وضع العرض\",\n    strict_mode: \"وضع صارم\",\n    field_details: \"تفاصيل الحقل\",\n    reset_view: \"إعادة ضبط العرض\",\n    show_grid: \"عرض الشبكة\",\n    show_cardinality: \"عرض التعددية\",\n    theme: \"السمة\",\n    light: \"فاتح\",\n    dark: \"داكن\",\n    zoom_in: \"تكبير\",\n    zoom_out: \"تصغير\",\n    fullscreen: \"ملء الشاشة\",\n    settings: \"الإعدادات\",\n    show_timeline: \"عرض الجدول الزمني\",\n    autosave: \"حفظ تلقائي\",\n    panning: \"التحريك\",\n    show_debug_coordinates: \"عرض إحداثيات التصحيح\",\n    transform: \"تحويل\",\n    viewbox: \"صندوق العرض\",\n    cursor_coordinates: \"إحداثيات المؤشر\",\n    coordinate_space: \"الفضاء\",\n    coordinate_space_screen: \"الشاشة\",\n    coordinate_space_diagram: \"المخطط\",\n    table_width: \"عرض الجدول\",\n    language: \"اللغة\",\n    flush_storage: \"مسح التخزين\",\n    are_you_sure_flush_storage:\n      \"هل أنت متأكد أنك تريد مسح التخزين؟ سيؤدي هذا إلى حذف جميع مخططاتك والقوالب المخصصة بشكل لا رجعة فيه.\",\n    storage_flushed: \"تم مسح التخزين\",\n    help: \"مساعدة\",\n    shortcuts: \"الاختصارات\",\n    ask_on_discord: \"اسألنا على ديسكورد\",\n    feedback: \"التعليقات\",\n    no_changes: \"لا تغييرات\",\n    loading: \"جارٍ التحميل...\",\n    last_saved: \"آخر حفظ\",\n    saving: \"جارٍ الحفظ...\",\n    failed_to_save: \"فشل في الحفظ\",\n    fit_window_reset: \"تكييف النافذة / إعادة ضبط\",\n    zoom: \"تكبير\",\n    add_table: \"إضافة جدول\",\n    add_area: \"إضافة منطقة\",\n    add_note: \"إضافة ملاحظة\",\n    add_type: \"إضافة نوع\",\n    to_do: \"مهام\",\n    tables: \"جداول\",\n    relationships: \"علاقات\",\n    subject_areas: \"المجالات الموضوعية\",\n    notes: \"ملاحظات\",\n    types: \"أنواع\",\n    search: \"بحث...\",\n    no_tables: \"لا توجد جداول\",\n    no_tables_text: \"ابدأ في بناء مخططك!\",\n    no_relationships: \"لا توجد علاقات\",\n    no_relationships_text: \"اسحب لربط الحقول وتشكيل العلاقات!\",\n    no_subject_areas: \"لا توجد مجالات موضوعية\",\n    no_subject_areas_text: \"أضف مجالات موضوعية لتجميع الجداول!\",\n    no_notes: \"لا توجد ملاحظات\",\n    no_notes_text: \"استخدم الملاحظات لتسجيل المعلومات الإضافية\",\n    no_types: \"لا توجد أنواع\",\n    no_types_text: \"اصنع أنواع البيانات المخصصة الخاصة بك\",\n    no_issues: \"لم يتم اكتشاف أي مشكلات.\",\n    strict_mode_is_on_no_issues: \"وضع صارم معطل لذا لن يتم عرض أي مشكلات.\",\n    name: \"الاسم\",\n    type: \"النوع\",\n    null: \"فارغ\",\n    not_null: \"غير فارغ\",\n    primary: \"أساسي\",\n    unique: \"فريد\",\n    autoincrement: \"زيادة تلقائية\",\n    default_value: \"القيمة الافتراضية\",\n    check: \"تعبير الفحص\",\n    this_will_appear_as_is: \"*سيظهر هذا في النص البرمجي المتولد كما هو.\",\n    comment: \"تعليق\",\n    add_field: \"إضافة حقل\",\n    values: \"القيم\",\n    size: \"الحجم\",\n    precision: \"الدقة\",\n    set_precision: \"تعيين الدقة: (الحجم، الأرقام)\",\n    use_for_batch_input: \"استخدم , للإدخال الدفعي\",\n    indices: \"المؤشرات\",\n    add_index: \"إضافة مؤشر\",\n    select_fields: \"تحديد الحقول\",\n    title: \"العنوان\",\n    not_set: \"غير معين\",\n    foreign: \"خارجي\",\n    cardinality: \"التعددية\",\n    on_update: \"عند التحديث\",\n    on_delete: \"عند الحذف\",\n    swap: \"تبديل\",\n    one_to_one: \"واحد إلى واحد\",\n    one_to_many: \"واحد إلى كثير\",\n    many_to_one: \"كثير إلى واحد\",\n    content: \"المحتوى\",\n    types_info:\n      \"تم تصميم هذه الميزة لقواعد البيانات العلائقية الكائنية مثل PostgreSQL.\\nإذا تم استخدامها مع MySQL أو MariaDB، سيتم توليد نوع JSON مع فحص التحقق المقابل.\\nإذا تم استخدامها مع SQLite، سيتم تحويلها إلى BLOB.\\nإذا تم استخدامها مع MSSQL، سيتم توليد نوع مستعار للحقل الأول.\",\n    table_deleted: \"تم حذف الجدول\",\n    area_deleted: \"تم حذف المنطقة\",\n    note_deleted: \"تم حذف الملاحظة\",\n    relationship_deleted: \"تم حذف العلاقة\",\n    type_deleted: \"تم حذف النوع\",\n    cannot_connect: \"لا يمكن الاتصال، الأعمدة لها أنواع مختلفة\",\n    copied_to_clipboard: \"تم النسخ إلى الحافظة\",\n    create_new_diagram: \"إنشاء مخطط جديد\",\n    cancel: \"إلغاء\",\n    open_diagram: \"فتح المخطط\",\n    rename_diagram: \"إعادة تسمية المخطط\",\n    export: \"تصدير\",\n    export_image: \"تصدير الصورة\",\n    create: \"إنشاء\",\n    confirm: \"تأكيد\",\n    last_modified: \"آخر تعديل\",\n    drag_and_drop_files: \"اسحب وأسقط الملف هنا أو انقر للتحميل.\",\n    upload_sql_to_generate_diagrams:\n      \"قم بتحميل ملف SQL لتوليد الجداول والأعمدة تلقائيًا.\",\n    overwrite_existing_diagram: \"الكتابة فوق المخطط الحالي\",\n    only_mysql_supported: \"*في الوقت الحالي، يتم دعم تحميل نصوص MySQL فقط.\",\n    blank: \"فارغ\",\n    filename: \"اسم الملف\",\n    table_w_no_name: \"تم إعلان جدول بدون اسم\",\n    duplicate_table_by_name: \"تكرار الجدول بالاسم '{{tableName}}'\",\n    empty_field_name: \"اسم الحقل فارغ في الجدول '{{tableName}}'\",\n    empty_field_type: \"نوع الحقل فارغ في الجدول '{{tableName}}'\",\n    no_values_for_field:\n      \"'{{fieldName}}' الحقل في الجدول '{{tableName}}' من النوع `{{type}}` ولكن لم يتم تحديد أي قيم\",\n    default_doesnt_match_type:\n      \"القيمة الافتراضية للحقل '{{fieldName}}' في الجدول '{{tableName}}' لا تتطابق مع نوعه\",\n    not_null_is_null:\n      \"'{{fieldName}}' الحقل في الجدول '{{tableName}}' ليس فارغًا ولكنه يحتوي على قيمة فارغة افتراضية\",\n    duplicate_fields:\n      \"حقول مكررة باسم '{{fieldName}}' في الجدول '{{tableName}}'\",\n    duplicate_index:\n      \"مؤشر مكرر بالاسم '{{indexName}}' في الجدول '{{tableName}}'\",\n    empty_index: \"المؤشر في الجدول '{{tableName}}' لا يشير إلى أي أعمدة\",\n    no_primary_key: \"الجدول '{{tableName}}' ليس له مفتاح أساسي\",\n    type_with_no_name: \"تم إعلان نوع بدون اسم\",\n    duplicate_types: \"أنواع مكررة بالاسم '{{typeName}}'\",\n    type_w_no_fields: \"تم إعلان نوع فارغ '{{typeName}}' بدون حقول\",\n    empty_type_field_name: \"اسم الحقل فارغ في النوع '{{typeName}}'\",\n    empty_type_field_type: \"نوع الحقل فارغ في النوع '{{typeName}}'\",\n    no_values_for_type_field:\n      \"'{{fieldName}}' الحقل في النوع '{{typeName}}' من النوع `{{type}}` ولكن لم يتم تحديد أي قيم\",\n    duplicate_type_fields:\n      \"حقول مكررة بالاسم '{{fieldName}}' في النوع '{{typeName}}'\",\n    duplicate_reference: \"مرجع مكرر بالاسم '{{refName}}'\",\n    circular_dependency: \"اعتماد دائري يشمل الجدول '{{refName}}'\",\n    timeline: \"الجدول الزمني\",\n    priority: \"الأولوية\",\n    none: \"لا شيء\",\n    low: \"منخفض\",\n    medium: \"متوسط\",\n    high: \"مرتفع\",\n    sort_by: \"ترتيب حسب\",\n    my_order: \"ترتيبي\",\n    completed: \"مكتمل\",\n    alphabetically: \"أبجديًا\",\n    add_task: \"إضافة مهمة\",\n    details: \"التفاصيل\",\n    no_tasks: \"ليس لديك أي مهام بعد.\",\n    no_activity: \"ليس لديك أي نشاط بعد.\",\n    move_element: \"نقل {{name}} إلى {{coords}}\",\n    edit_area: \"{{extra}} تحرير المنطقة {{areaName}}\",\n    delete_area: \"حذف المنطقة {{areaName}}\",\n    edit_note: \"{{extra}} تحرير الملاحظة {{noteTitle}}\",\n    delete_note: \"حذف الملاحظة {{noteTitle}}\",\n    edit_table: \"{{extra}} تحرير الجدول {{tableName}}\",\n    delete_table: \"حذف الجدول {{tableName}}\",\n    edit_type: \"{{extra}} تحرير النوع {{typeName}}\",\n    delete_type: \"حذف النوع {{typeName}}\",\n    add_relationship: \"إضافة علاقة\",\n    edit_relationship: \"{{extra}} تحرير العلاقة {{refName}}\",\n    delete_relationship: \"حذف العلاقة {{refName}}\",\n    not_found: \"لم يتم العثور على\",\n    pick_db: \"اختر قاعدة البيانات\",\n    generic: \"عام\",\n    generic_description:\n      \"يمكن تصدير المخططات العامة إلى أي نوع SQL ولكن تدعم أنواع بيانات قليلة.\",\n    enums: \"القيم المعدودة\",\n    add_enum: \"إضافة قيمة معدودة\",\n    edit_enum: \"{{extra}} تحرير القيمة المعدودة {{enumName}}\",\n    delete_enum: \"حذف القيمة المعدودة\",\n    enum_w_no_name: \"تم العثور على قيمة معدودة بدون اسم\",\n    enum_w_no_values: \"تم العثور على قيمة معدودة '{{enumName}}' بدون قيم\",\n    duplicate_enums: \"قيم معدودة مكررة بالاسم '{{enumName}}'\",\n    no_enums: \"لا توجد قيم معدودة\",\n    no_enums_text: \"حدد القيم المعدودة هنا\",\n    declare_array: \"إعلان مصفوفة\",\n    empty_index_name: \"تم إعلان مؤشر بدون اسم في الجدول '{{tableName}}'\",\n    didnt_find_diagram: \"عفوًا! لم يتم العثور على المخطط.\",\n  },\n};\n\nexport { ar, arabic };\n"
  },
  {
    "path": "src/i18n/locales/as.js",
    "content": "const assamese = {\n    name: \"Assamese\",\n    native_name: \"অসমীয়া\",\n    code: \"as\",\n  };\n  \n\n\nconst as = {\n    translation: {\n      report_bug: \"এক টো সমস্যা প্ৰতিবেদন কৰক\",\n      import: \"আমদানি\",\n      inherits: \"উত্তৰাধিকাৰ লয়া কৰিছে\",\n      merging_column_w_inherited_definition:\n        \"টেবুল '{{tableName}}' ৰ '{{fieldName}}' কলাম থকা উত্তৰাধিকৃত সংজ্ঞাৰ সৈতে মাৰ্জ কৰা হ'ব\",\n      import_from: \"ৰ পৰা আমদানি কৰক\",\n      file: \"ফাইল\",\n      new: \"নতুন\",\n      new_window: \"নতুন উইন্ডো\",\n      no_saved_diagrams: \"আপোনাৰ সংৰক্ষিত কোনো ডায়াগ্ৰাম নাই\",\n      open: \"খোলক\",\n      open_recent: \"সাম্প্ৰতিক খোলক\",\n      save: \"সংৰক্ষণ\",\n      save_as: \"এই নামত সংৰক্ষণ কৰক\",\n      save_as_template: \"টেমপ্লেট হিচাপে সংৰক্ষণ কৰক\",\n      template_saved: \"টেমপ্লেট সংৰক্ষিত!\",\n      rename: \"ৰ নাম সলনি কৰক\",\n      delete_diagram: \"ডায়াগ্ৰাম মচি পেলাওক\",\n      are_you_sure_delete_diagram:\n        \"আপুনি নিশ্চিতনেকি এই ডায়াগ্ৰাম মচি পেলাবলৈ? এই কাৰ্য্য অপরিবর্তনীয়।\",\n      oops_smth_went_wrong: \"অ'পচ! কিবা এটা ভুল হৈ গ'ল।\",\n      import_diagram: \"ডায়াগ্ৰাম আমদানি কৰক\",\n      import_from_source: \"SQL ৰ পৰা আমদানি কৰক\",\n      export_as: \"এই হিচাপে ৰপ্তানি কৰক\",\n      export_source: \"SQL ৰূপে ৰপ্তানি কৰক\",\n      models: \"মডেলসমূহ\",\n      exit: \"বাহিৰ হওক\",\n      edit: \"সম্পাদনা\",\n      undo: \"অপ্রয়োগ কৰক\",\n      redo: \"পুনৰ কৰক\",\n      clear: \"মচি পেলাওক\",\n      are_you_sure_clear:\n        \"আপুনি নিশ্চিতনে এই ডায়াগ্ৰাম মচি পেলাবলৈ চাহিব? এইটো অপরিবর্তনীয়।\",\n      cut: \"কাটক\",\n      copy: \"কপি\",\n      paste: \"আটোক\",\n      duplicate: \"নকল\",\n      delete: \"মচি পেলাওক\",\n      copy_as_image: \"চিত্ৰ হিচাপে কপি কৰক\",\n      view: \"দৰ্শন\",\n      header: \"মেনুৱাৰ\",\n      sidebar: \"চাইডবাৰ\",\n      issues: \"সমস্যাসমূহ\",\n      presentation_mode: \"প্ৰেজেন্টেশ্যন মোড\",\n      strict_mode: \"কঠোৰ মোড\",\n      field_details: \"ক্ষেত্ৰৰ বিৱৰণ\",\n      reset_view: \"দৃষ্টি ৰিসেট কৰক\",\n      show_grid: \"গ্ৰিড প্ৰদৰ্শন কৰক\",\n      snap_to_grid: \"গ্ৰিডত চিপকাওক\",\n      show_datatype: \"ডাটা প্ৰকাৰ দেখুৱাওক\",\n      show_cardinality: \"কাৰ্ডিনেলিটি দেখুৱাওক\",\n      theme: \"থীম\",\n      light: \"আলো\",\n      dark: \"অন্ধকাৰ\",\n      zoom_in: \"জুম ইন\",\n      zoom_out: \"জুম আউট\",\n      fullscreen: \"স্ক্ৰীণ ফুলস্ক্ৰীণ\",\n      settings: \"ছেটিংছ\",\n      show_timeline: \"টাইমলাইন দেখুৱাওক\",\n      autosave: \"স্বয়ংক্ৰিয় সংৰক্ষণ\",\n      panning: \"পেনিং\",\n      show_debug_coordinates: \"ডিবাগ স্থানাঙ্ক দেখুৱাওক\",\n      transform: \"ৰূপান্তৰ\",\n      viewbox: \"ভিউ বক্স\",\n      cursor_coordinates: \"কৰ্ছাৰ স্থানাঙ্ক\",\n      coordinate_space: \"স্থান\",\n      coordinate_space_screen: \"স্ক্ৰীণ\",\n      coordinate_space_diagram: \"ডায়াগ্ৰাম\",\n      table_width: \"টেবুলৰ প্ৰস্থ\",\n      language: \"ভাষা\",\n      flush_storage: \"সংগ্ৰহস্থল খালি কৰক\",\n      are_you_sure_flush_storage:\n        \"আপুনি নিশ্চিতনে সংগ্রহস্থল খালি কৰিব? এইয়ে আপোনাৰ সকলো ডায়াগ্ৰাম আৰু কাষ্টম টেমপ্লেট অনন্তকালৰ বাবে মচি দিয়া হ'ব।\",\n      storage_flushed: \"সংগ্ৰহস্থল খালী কৰা হ'ল\",\n      help: \"সাহায্য\",\n      shortcuts: \"শৰ্টকাটসমূহ\",\n      ask_on_discord: \"Discord ত সোধক\",\n      feedback: \"প্ৰতিক্ৰিয়া\",\n      no_changes: \"কোনো পৰিবর্তন নাথাকে\",\n      loading: \"লোড কৰা হৈছে...\",\n      last_saved: \"শেষত সংৰক্ষিত\",\n      saving: \"সংৰক্ষণ কৰা হৈছে...\",\n      failed_to_save: \"সংৰক্ষণ বিফল\",\n      fit_window_reset: \"উইন্ডো মানাই / ৰিসেট\",\n      zoom: \"জুম\",\n      add_table: \"টেবুল যোগ কৰক\",\n      add_area: \"এৰিয়া যোগ কৰক\",\n      add_note: \"নোট যোগ কৰক\",\n      add_type: \"টাইপ যোগ কৰক\",\n      to_do: \"কৰিবলৈ\",\n      tables: \"টেবুলসমূহ\",\n      relationships: \"সম্পৰ্কসমূহ\",\n      subject_areas: \"বিষয় ক্ষেত্ৰসমূহ\",\n      notes: \"নোটসমূহ\",\n      types: \"টাইপসমূহ\",\n      search: \"অনুসন্ধান...\",\n      no_tables: \"কোনো টেবুল নাই\",\n      no_tables_text: \"আপোনাৰ ডায়াগ্ৰাম নিৰ্মাণ কৰা আৰম্ভ কৰক!\",\n      no_relationships: \"কোনো সম্পৰ্ক নাই\",\n      no_relationships_text: \"ক্ষেত্ৰসমূহ সংযোগ কৰিবলৈ টানক আৰু সম্পৰ্ক গঠন কৰক!\",\n      no_subject_areas: \"কোনো বিষয় ক্ষেত্ৰ নাই\",\n      no_subject_areas_text: \"টেবুলসমূহ গ্ৰুপ কৰিবলৈ বিষয় ক্ষেত্ৰসমূহ যোগ কৰক!\",\n      no_notes: \"কোনো নোট নাই\",\n      no_notes_text: \"অতिरिक्त তথ্য ৰেকৰ্ড কৰিবলৈ নোট ব্যৱহাৰ কৰক\",\n      no_types: \"কোনো টাইপ নাই\",\n      no_types_text: \"আপোনাৰ নিজা কাষ্টম ডাটা টাইপ বনাওক\",\n      no_issues: \"কোনো সমস্যা চিনাক্ত হোৱা নাই।\",\n      strict_mode_is_on_no_issues:\n        \"কঠোৰ মোড বন্ধ আছে সেয়ে কোনো সমস্যা দেখুওৱা নহ'ব।\",\n      name: \"নাম\",\n      type: \"টাইপ\",\n      null: \"Null\",\n      not_null: \"Null নহয়\",\n      nullable: \"নিউল কৰিব পৰা যায়\",\n      primary: \"প্ৰাথমিক\",\n      unique: \"একক\",\n      autoincrement: \"স্বয়ং-বৃদ্ধি\",\n      default_value: \"ডিফল্ট\",\n      check: \"চেক এক্সপ্ৰেছন\",\n      this_will_appear_as_is: \"*এইটো জেনাৰেট কৰা স্ক্ৰিপ্টত একে ৰূপে দেখা যাব।\",\n      comment: \"মন্তব্য\",\n      add_field: \"ক্ষেত্ৰ যোগ কৰক\",\n      values: \"মানসমূহ\",\n      size: \"আকাৰ\",\n      precision: \"নিখুঁততা\",\n      set_precision: \"নিখুঁততা নিৰ্ধাৰণ: 'size, digits'\",\n      use_for_batch_input: \"ব্যাচ ইনপুটৰ বাবে , ব্যৱহাৰ কৰক\",\n      indices: \"সূচক\",\n      add_index: \"সূচক যোগ কৰক\",\n      select_fields: \"ক্ষেত্ৰসমূহ বাছনি কৰক\",\n      title: \"শিৰোনাম\",\n      not_set: \"নির্ধাৰিত নহয়\",\n      foreign: \"বৈদেশিক\",\n      cardinality: \"কাৰ্ডিনেলিটি\",\n      on_update: \"আপডেটত\",\n      on_delete: \"মচা হলে\",\n      swap: \"সুবল\",\n      one_to_one: \"এটাৰ পৰা এটালৈ\",\n      one_to_many: \"এটাৰ পৰা বহু\",\n      many_to_one: \"বহুতৰ পৰা এটা\",\n      content: \"বিষয়বস্তু\",\n      types_info:\n        \"এই ফিচাৰটো PostgreSQL ধৰণৰ অবজেক্ট-ৰিলেশনেল DBMSসমূহৰ বাবে উদ্দেশ্য কৰা হৈছে।\\nMySQL বা MariaDB ৰ বাবে ব্যৱহাৰ কৰিলে এটা JSON টাইপ জেনাৰেট কৰা হ'ব আৰু তদনুসাৰ json ভেলিডেশ্যন চেক যোগ কৰা হ'ব।\\nSQLite ৰ বাবে ই BLOB ত ৰূপান্তৰিত কৰা হ'ব।\\nMSSQL ৰ বাবে প্ৰথম ক্ষেত্ৰৰ টাইপৰ এক টাইপ আলিয়াচ সৃষ্টি কৰা হ'ব।\",\n      table_deleted: \"টেবুল মচি দিয়া হ'ল\",\n      area_deleted: \"এৰিয়া মচি দিয়া হ'ল\",\n      note_deleted: \"নোট মচি দিয়া হ'ল\",\n      relationship_deleted: \"সম্পৰ্ক মচি দিয়া হ'ল\",\n      type_deleted: \"টাইপ মচি দিয়া হ'ল\",\n      cannot_connect: \"সংযোগ কৰিব পৰা নগ'ল, কলামসমূহৰ টাইপ ভিন্ন\",\n      copied_to_clipboard: \"ক্লিপব'ৰ্ডত কপি কৰা হ'ল\",\n      create_new_diagram: \"নতুন ডায়াগ্ৰাম সৃষ্টি কৰক\",\n      cancel: \"বাতিল\",\n      open_diagram: \"ডায়াগ্ৰাম খোলক\",\n      rename_diagram: \"ডায়াগ্ৰামৰ নাম সলনি কৰক\",\n      export: \"ৰপ্তানি\",\n      export_image: \"চিত্ৰ ৰূপে ৰপ্তানি\",\n      create: \"সৃষ্টি কৰক\",\n      confirm: \"নিশ্চিত কৰক\",\n      last_modified: \"শেষ পৰিবর্তন\",\n      drag_and_drop_files: \"ফাইলটো ইয়াত টানি নেমাওক বা আপলোড কৰিবলৈ ক্লিক কৰক।\",\n      upload_sql_to_generate_diagrams:\n        \"আপোনাৰ টেবুল আৰু কলাম স্বয়ংক্ৰিয়ভাৱে সৃষ্টি কৰিবলৈ এটা sql ফাইল আপলোড কৰক।\",\n      overwrite_existing_diagram: \"অস্তিত্বশীল ডায়াগ্ৰামৰ ওপৰত লিখা হ'ব\",\n      only_mysql_supported:\n        \"* বৰ্তমানে কেৱল MySQL স্ক্ৰিপ্টসমূহ লোড কৰা সমৰ্থিত।\",\n      blank: \"ফাঁকা\",\n      filename: \"ফাইল নাম\",\n      table_w_no_name: \"নাম নাথকা টেবুল ঘোষণা কৰা হ'ল\",\n      duplicate_table_by_name: \"নাম '{{tableName}}' ৰ দ্বাৰা টেবুল নকল\",\n      empty_field_name: \"টেবুল '{{tableName}}' ত খালী ক্ষেত্ৰ `name`\",\n      empty_field_type: \"টেবুল '{{tableName}}' ত খালী ক্ষেত্ৰ `type`\",\n      no_values_for_field:\n        \"টেবুল '{{tableName}}' ৰ '{{fieldName}}' ক্ষেত্ৰৰ টাইপ `{{type}}` কিন্তু মানসমূহ দিয়া হোৱা নাই\",\n      default_doesnt_match_type:\n        \"টেবুল '{{tableName}}' ৰ '{{fieldName}}' ক্ষেত্ৰৰ ডিফল্ট মান তাত নিযুক্ত টাইপৰ সৈতে মিলে নাযায়\",\n      not_null_is_null:\n        \"টেবুল '{{tableName}}' ৰ '{{fieldName}}' ক্ষেত্ৰটো NOT NULL কিন্তু ডিফল্ট NULL আছে\",\n      duplicate_fields:\n        \"টেবুল '{{tableName}}' ত নাম '{{fieldName}}' দ্বাৰা ক্ষেত্ৰসমূহ নকল\",\n      duplicate_index:\n        \"টেবুল '{{tableName}}' ত নাম '{{indexName}}' দ্বাৰা সূচক নকল\",\n      empty_index: \"টেবুল '{{tableName}}' ত সূচকে কোনো কলাম সূচীকৰে নালাগে\",\n      no_primary_key: \"টেবুল '{{tableName}}' ত কোনো প্ৰায়মাৰী কী নাই\",\n      type_with_no_name: \"নাম নাথকা এটা টাইপ ঘোষণা কৰা হ'ল\",\n      duplicate_types: \"নাম '{{typeName}}' দ্বাৰা টাইপসমূহ নকল\",\n      type_w_no_fields: \"ক্ষেত্ৰ নাথকা খালী টাইপ '{{typeName}}' ঘোষণা কৰা হ'ল\",\n      empty_type_field_name: \"টাইপ '{{typeName}}' ত খালী ক্ষেত্ৰ `name`\",\n      empty_type_field_type: \"টাইপ '{{typeName}}' ত খালী ক্ষেত্ৰ `type`\",\n      no_values_for_type_field:\n        \"টাইপ '{{typeName}}' ৰ '{{fieldName}}' ক্ষেত্ৰৰ টাইপ `{{type}}` কিন্তু মানসমূহ দিয়া হোৱা নাই\",\n      duplicate_type_fields:\n        \"টাইপ '{{typeName}}' ত নাম '{{fieldName}}' দ্বাৰা ক্ষেত্ৰসমূহ নকল\",\n      duplicate_reference: \"নাম '{{refName}}' দ্বাৰা ৰেফাৰেঞ্চ নকল\",\n      circular_dependency: \"চক্ৰাকাৰ নিৰ্ভৰশীলতা য'ত টেবুল '{{refName}}' জড়িত\",\n      timeline: \"টাইমলাইন\",\n      priority: \"প্ৰাধান্য\",\n      none: \"কোনোটি নাই\",\n      low: \"নিম্ন\",\n      medium: \"মধ্যম\",\n      high: \"উচ্চ\",\n      sort_by: \"ইতিমধ্যে ব্যৱস্থা কৰক\",\n      my_order: \"মোৰ শৃংখলা\",\n      completed: \"সমাপ্ত\",\n      alphabetically: \"আলফাবেটিকেলি\",\n      add_task: \"কাজ যোগ কৰক\",\n      details: \"বিৱৰণ\",\n      no_tasks: \"আপোনাৰ এতিয়ালৈকে কোনো কাম নাথাকে।\",\n      no_activity: \"আপোনাৰ এতিয়ালৈকে কোনো কার্যকলাপ নাথাকে।\",\n      move_element: \"চলাওক {{name}} ক {{coords}} ৰ পৰা\",\n      edit_area: \"{{extra}} এৰিয়া সম্পাদনা কৰক {{areaName}}\",\n      delete_area: \"এৰিয়া মচি পেলাওক {{areaName}}\",\n      edit_note: \"{{extra}} নোট সম্পাদনা কৰক {{noteTitle}}\",\n      delete_note: \"নোট মচি পেলাওক {{noteTitle}}\",\n      edit_table: \"{{extra}} টেবুল সম্পাদনা কৰক {{tableName}}\",\n      delete_table: \"টেবুল মচি পেলাওক {{tableName}}\",\n      edit_type: \"{{extra}} টাইপ সম্পাদনা কৰক {{typeName}}\",\n      delete_type: \"টাইপ মচি পেলাওক {{typeName}}\",\n      add_relationship: \"সম্পৰ্ক যোগ কৰক\",\n      edit_relationship: \"{{extra}} সম্পর্ক সম্পাদনা কৰক {{refName}}\",\n      delete_relationship: \"সম্পৰ্ক মচি পেলাওক {{refName}}\",\n      not_found: \"নপোৱা গ'ল\",\n      pick_db: \"এখন ডেটাবেছ বাচক\",\n      generic: \"জেনাৰিক\",\n      generic_description:\n        \"জেনাৰিক ডায়াগ্ৰামসমূহ যিকোনো SQL ফ্লেভাৰৰ বাবে ৰপ্তানি কৰিব পৰা যায় কিন্তু কম ডাটা টাইপ সমৰ্থন কৰে।\",\n      enums: \"এনামসমূহ\",\n      add_enum: \"এনাম যোগ কৰক\",\n      edit_enum: \"{{extra}} এনাম সম্পাদনা কৰক {{enumName}}\",\n      delete_enum: \"এনাম মচি পেলাওক\",\n      enum_w_no_name: \"নাম নাথকা এনাম পোৱা গ'ল\",\n      enum_w_no_values: \"এনাম '{{enumName}}' ত মানসমূহ নাথাকে\",\n      duplicate_enums: \"নাম '{{enumName}}' দ্বাৰা এনামসমূহ নকল\",\n      enum_deleted: \"এনাম মচি পেলাওক\",\n      no_enums: \"কোনো এনাম নাই\",\n      no_enums_text: \"এনামসমূহ ইয়াত সংজ্ঞায়িত কৰক\",\n      declare_array: \"এৰে তাল ঘোষণা কৰক\",\n      empty_index_name: \"টেবুল '{{tableName}}' ত নাম নাথকা সূচক ঘোষণা কৰা হ'ল\",\n      didnt_find_diagram: \"অপচ! ডায়াগ্ৰামটা পোৱা নাযায়।\",\n      unsigned: \"অ-চিহ্নিত (Unsigned)\",\n      share: \"শ্বেয়াৰ\",\n      unshare: \"শ্বেয়াৰ বন্ধ\",\n      copy_link: \"লিংক কপি কৰক\",\n      readme: \"README\",\n      failed_to_load: \"লোড কৰিবলৈ বিফল। নিশ্চিত কৰক লিংকটো সঠিক।\",\n      share_info:\n        \"* এই লিংক শ্বেয়াৰ কৰোঁতে এটা লাইভ ৰিয়েল-টাইম সহযোগিতা সেশ্যন সৃষ্টি নহ'ব।\",\n      show_relationship_labels: \"সম্পৰ্ক লেবেলসমূহ দেখুৱাওক\",\n      docs: \"ডকুমেন্টচ\",\n      supported_types: \"সমৰ্থিত ফাইল টাইপসমূহ:\",\n      bulk_update: \"বাল্ক আপডেট\",\n      multiselect: \"বহু-নিৰ্বাচন\",\n      export_saved_data: \"সংৰক্ষিত ডাটা ৰপ্তানি কৰক\",\n      dbml_view: \"DBML দৃষ্টি\",\n      tab_view: \"ট্যাব দৃষ্টি\",\n      label: \"লেবেল\",\n      many_side_label: \"বহু(n) পাৰৰ লেবেল\",\n      version: \"সংস্কৰণ\",\n      versions: \"সংস্কৰণবোৰ\",\n      no_saved_versions: \"কোনো সংৰক্ষিত সংস্কৰণ নাই\",\n      record_version: \"সংস্কৰণ ৰেকৰ্ড কৰক\",\n      commited_at: \"কমিট কৰা হৈছিল\",\n      read_only: \"পড়িবলৈহে\",\n      continue: \"জাৰি ৰাখক\",\n      restore_version: \"সংস্কৰণ পুনৰুদ্ধাৰ কৰক\",\n      restore_warning: \" অন্য সংস্কৰণ লোড কৰিলে যিকোনো পৰিবর্তন ওপৰ-লিখা হ'ব।\",\n      return_to_current: \"ডায়াগ্ৰামলৈ উভতক\",\n      no_changes_to_record: \"ৰেকৰ্ড কৰিবলৈ কোনো পৰিবর্তন নাই\",\n      click_to_view: \"দেখিবলৈ ক্লিক কৰক\",\n      load_more: \"অধিক লোড কৰক\",\n      clear_cache: \"কেচ মচি পেলাওক\",\n      cache_cleared: \"কেচ মচি দিয়া হ'ল\",\n      failed_to_record_version: \"সংস্কৰণ ৰেকৰ্ড কৰিবলৈ বিফল\",\n      failed_to_load_diagram: \"ডায়াগ্ৰাম লোড কৰিবলৈ বিফল\",\n      see_all: \"সকলো চাওক\",\n      insert_sql: \"SQL প্ৰবিষ্ট কৰক\",\n      upload_file: \"ফাইল আপলোড কৰক\",\n    },\n  };\n\n  \nexport { as, assamese };"
  },
  {
    "path": "src/i18n/locales/bg.js",
    "content": "const bulgarian = {\n    name: \"Bulgarian\",\n    native_name: \"Български\",\n    code: \"bg\",\n};\n\nconst bg = {\n    translation: {\n        report_bug: \"Докладвай грешка\",\n        import: \"Импорт\",\n        inherits: \"Наследява\",\n        merging_column_w_inherited_definition:\n            \"Колона '{{fieldName}}' в таблица '{{tableName}}' с наследена дефиниция ще бъде обединена\",\n        import_from: \"Импорт от\",\n        file: \"Файл\",\n        new: \"Нов\",\n        new_window: \"Нов прозорец\",\n        no_saved_diagrams: \"Нямате запазени диаграми\",\n        open: \"Отвори\",\n        open_recent: \"Отвори скорошни\",\n        save: \"Запази\",\n        save_as: \"Запази като\",\n        save_as_template: \"Запази като шаблон\",\n        template_saved: \"Шаблонът е запазен!\",\n        rename: \"Преименувай\",\n        delete_diagram: \"Изтрий диаграма\",\n        are_you_sure_delete_diagram:\n            \"Сигурни ли сте, че искате да изтриете тази диаграма? Тази операция е необратима.\",\n        oops_smth_went_wrong: \"Опа! Нещо се обърка.\",\n        import_diagram: \"Импорт на диаграма\",\n        import_from_source: \"Импорт от SQL\",\n        export_as: \"Експорт като\",\n        export_source: \"Експорт на SQL\",\n        models: \"Модели\",\n        exit: \"Изход\",\n        edit: \"Редактиране\",\n        undo: \"Отмени\",\n        redo: \"Повтори\",\n        clear: \"Изчисти\",\n        are_you_sure_clear:\n            \"Сигурни ли сте, че искате да изчистите диаграмата? Това е необратимо.\",\n        cut: \"Изрежи\",\n        copy: \"Копирай\",\n        paste: \"Постави\",\n        duplicate: \"Дублирай\",\n        delete: \"Изтрий\",\n        copy_as_image: \"Копирай като изображение\",\n        view: \"Изглед\",\n        header: \"Лента с менюта\",\n        sidebar: \"Странична лента\",\n        issues: \"Проблеми\",\n        presentation_mode: \"Режим на презентация\",\n        strict_mode: \"Строг режим\",\n        field_details: \"Детайли на полето\",\n        reset_view: \"Възстанови изгледа\",\n        show_grid: \"Покажи мрежа\",\n        snap_to_grid: \"Прилепване към мрежата\",\n        show_datatype: \"Покажи тип данни\",\n        show_cardinality: \"Покажи кардиналност\",\n        theme: \"Тема\",\n        light: \"Светла\",\n        dark: \"Тъмна\",\n        zoom_in: \"Увеличи\",\n        zoom_out: \"Намали\",\n        fullscreen: \"Цял екран\",\n        settings: \"Настройки\",\n        show_timeline: \"Покажи времева линия\",\n        autosave: \"Автоматично запазване\",\n        panning: \"Панорамиране\",\n        show_debug_coordinates: \"Покажи координати за отстраняване на грешки\",\n        transform: \"Трансформирай\",\n        viewbox: \"View Box\",\n        cursor_coordinates: \"Координати на курсора\",\n        coordinate_space: \"Пространство\",\n        coordinate_space_screen: \"Екран\",\n        coordinate_space_diagram: \"Диаграма\",\n        table_width: \"Ширина на таблицата\",\n        language: \"Език\",\n        flush_storage: \"Изчисти хранилището\",\n        are_you_sure_flush_storage:\n            \"Сигурни ли сте, че искате да изчистите хранилището? Това ще изтрие необратимо всички ваши диаграми и потребителски шаблони.\",\n        storage_flushed: \"Хранилището е изчистено\",\n        help: \"Помощ\",\n        shortcuts: \"Клавишни комбинации\",\n        ask_on_discord: \"Попитайте ни в Discord\",\n        feedback: \"Обратна връзка\",\n        no_changes: \"Няма промени\",\n        loading: \"Зареждане...\",\n        last_saved: \"Последно запазено\",\n        saving: \"Запазване...\",\n        failed_to_save: \"Неуспешно запазване\",\n        fit_window_reset: \"Побиране в прозореца / Нулиране\",\n        zoom: \"Мащаб\",\n        add_table: \"Добави таблица\",\n        add_area: \"Добави област\",\n        add_note: \"Добави бележка\",\n        add_type: \"Добави тип\",\n        to_do: \"Задачи\",\n        tables: \"Таблици\",\n        relationships: \"Връзки\",\n        subject_areas: \"Предметни области\",\n        notes: \"Бележки\",\n        types: \"Типове\",\n        search: \"Търсене...\",\n        no_tables: \"Няма таблици\",\n        no_tables_text: \"Започнете да изграждате вашата диаграма!\",\n        no_relationships: \"Няма връзки\",\n        no_relationships_text: \"Плъзнете, за да свържете полета и да създадете връзки!\",\n        no_subject_areas: \"Няма предметни области\",\n        no_subject_areas_text: \"Добавете предметни области за групиране на таблици!\",\n        no_notes: \"Няма бележки\",\n        no_notes_text: \"Използвайте бележки за записване на допълнителна информация\",\n        no_types: \"Няма типове\",\n        no_types_text: \"Направете свои собствени типове данни\",\n        no_issues: \"Не са открити проблеми.\",\n        strict_mode_is_on_no_issues:\n            \"Строгият режим е изключен, така че няма да се показват проблеми.\",\n        name: \"Име\",\n        type: \"Тип\",\n        null: \"Null\",\n        not_null: \"Not null\",\n        nullable: \"Nullable\",\n        primary: \"Primary\",\n        unique: \"Unique\",\n        autoincrement: \"Autoincrement\",\n        default_value: \"По подразбиране\",\n        check: \"Check израз\",\n        this_will_appear_as_is: \"*Това ще се появи в генерирания скрипт както е.\",\n        comment: \"Коментар\",\n        add_field: \"Добави поле\",\n        values: \"Стойности\",\n        size: \"Размер\",\n        precision: \"Точност\",\n        set_precision: \"Задай точност: 'размер, цифри'\",\n        use_for_batch_input: \"Използвай , за групово въвеждане\",\n        indices: \"Индекси\",\n        add_index: \"Добави индекс\",\n        select_fields: \"Избери полета\",\n        title: \"Заглавие\",\n        not_set: \"Не е зададено\",\n        foreign: \"Foreign\",\n        cardinality: \"Кардиналност\",\n        on_update: \"При обновяване\",\n        on_delete: \"При изтриване\",\n        swap: \"Размени\",\n        one_to_one: \"Едно към едно\",\n        one_to_many: \"Едно към много\",\n        many_to_one: \"Много към едно\",\n        content: \"Съдържание\",\n        types_info:\n            \"Тази функция е предназначена за обектно-релационни СУБД като PostgreSQL.\\nАко се използва за MySQL или MariaDB, ще бъде генериран JSON тип със съответната проверка за валидиране на json.\\nАко се използва за SQLite, ще бъде преведен като BLOB.\\nАко се използва за MSSQL, ще бъде генериран псевдоним на типа към първото поле.\",\n        table_deleted: \"Таблицата е изтрита\",\n        area_deleted: \"Областта е изтрита\",\n        note_deleted: \"Бележката е изтрита\",\n        relationship_deleted: \"Връзката е изтрита\",\n        type_deleted: \"Типът е изтрит\",\n        cannot_connect: \"Не може да се свърже, колоните имат различни типове\",\n        copied_to_clipboard: \"Копирано в клипборда\",\n        create_new_diagram: \"Създай нова диаграма\",\n        cancel: \"Отказ\",\n        open_diagram: \"Отвори диаграма\",\n        rename_diagram: \"Преименувай диаграма\",\n        export: \"Експорт\",\n        export_image: \"Експорт на изображение\",\n        create: \"Създай\",\n        confirm: \"Потвърди\",\n        last_modified: \"Последна промяна\",\n        drag_and_drop_files: \"Плъзнете и пуснете файла тук или кликнете за качване.\",\n        upload_sql_to_generate_diagrams:\n            \"Качете sql файл, за да генерирате автоматично вашите таблици и колони.\",\n        overwrite_existing_diagram: \"Презапиши съществуващата диаграма\",\n        only_mysql_supported:\n            \"*За момента се поддържа зареждане само на MySQL скриптове.\",\n        blank: \"Празен\",\n        filename: \"Име на файл\",\n        table_w_no_name: \"Декларирана е таблица без име\",\n        duplicate_table_by_name: \"Дублирана таблица с име '{{tableName}}'\",\n        empty_field_name: \"Празно поле `name` в таблица '{{tableName}}'\",\n        empty_field_type: \"Празно поле `type` в таблица '{{tableName}}'\",\n        no_values_for_field:\n            \"Поле '{{fieldName}}' на таблица '{{tableName}}' е от тип `{{type}}`, но не са зададени стойности\",\n        default_doesnt_match_type:\n            \"Стойността по подразбиране за поле '{{fieldName}}' в таблица '{{tableName}}' не отговаря на неговия тип\",\n        not_null_is_null:\n            \"Поле '{{fieldName}}' на таблица '{{tableName}}' е NOT NULL, но има стойност по подразбиране NULL\",\n        duplicate_fields:\n            \"Дублирани полета на таблица с име '{{fieldName}}' в таблица '{{tableName}}'\",\n        duplicate_index:\n            \"Дублиран индекс с име '{{indexName}}' в таблица '{{tableName}}'\",\n        empty_index: \"Индекс в таблица '{{tableName}}' не индексира никакви колони\",\n        no_primary_key: \"Таблица '{{tableName}}' няма първичен ключ\",\n        type_with_no_name: \"Деклариран е тип без име\",\n        duplicate_types: \"Дублирани типове с име '{{typeName}}'\",\n        type_w_no_fields: \"Деклариран е празен тип '{{typeName}}' без полета\",\n        empty_type_field_name: \"Празно поле `name` в тип '{{typeName}}'\",\n        empty_type_field_type: \"Празно поле `type` в тип '{{typeName}}'\",\n        no_values_for_type_field:\n            \"Поле '{{fieldName}}' на тип '{{typeName}}' е от тип `{{type}}`, но не са зададени стойности\",\n        duplicate_type_fields:\n            \"Дублирани полета на тип с име '{{fieldName}}' в тип '{{typeName}}'\",\n        duplicate_reference: \"Дублирана референция с име '{{refName}}'\",\n        circular_dependency: \"Кръгова зависимост включваща таблица '{{refName}}'\",\n        timeline: \"Времева линия\",\n        priority: \"Приоритет\",\n        none: \"Няма\",\n        low: \"Нисък\",\n        medium: \"Среден\",\n        high: \"Висок\",\n        sort_by: \"Сортирай по\",\n        my_order: \"Моят ред\",\n        completed: \"Завършен\",\n        alphabetically: \"Азбучен ред\",\n        add_task: \"Добави задача\",\n        details: \"Детайли\",\n        no_tasks: \"Все още нямате задачи.\",\n        no_activity: \"Все още нямате активност.\",\n        move_element: \"Премести {{name}} на {{coords}}\",\n        edit_area: \"{{extra}} Редактирай област {{areaName}}\",\n        delete_area: \"Изтрий област {{areaName}}\",\n        edit_note: \"{{extra}} Редактирай бележка {{noteTitle}}\",\n        delete_note: \"Изтрий бележка {{noteTitle}}\",\n        edit_table: \"{{extra}} Редактирай таблица {{tableName}}\",\n        delete_table: \"Изтрий таблица {{tableName}}\",\n        edit_type: \"{{extra}} Редактирай тип {{typeName}}\",\n        delete_type: \"Изтрий тип {{typeName}}\",\n        add_relationship: \"Добави връзка\",\n        edit_relationship: \"{{extra}} Редактирай връзка {{refName}}\",\n        delete_relationship: \"Изтрий връзка {{refName}}\",\n        not_found: \"Не е намерено\",\n        pick_db: \"Изберете база данни\",\n        generic: \"Generic\",\n        generic_description:\n            \"Generic диаграмите могат да бъдат експортирани към всеки SQL вариант, но поддържат малко типове данни.\",\n        enums: \"Enums\",\n        add_enum: \"Добави enum\",\n        edit_enum: \"{{extra}} Редактирай enum {{enumName}}\",\n        delete_enum: \"Изтрий enum\",\n        enum_w_no_name: \"Намерен е enum без име\",\n        enum_w_no_values: \"Намерен е enum '{{enumName}}' без стойности\",\n        duplicate_enums: \"Дублирани enums с име '{{enumName}}'\",\n        enum_deleted: \"Enum изтрит\",\n        no_enums: \"Няма enums\",\n        no_enums_text: \"Дефинирайте enums тук\",\n        declare_array: \"Декларирай масив\",\n        empty_index_name: \"Деклариран е индекс без име в таблица '{{tableName}}'\",\n        didnt_find_diagram: \"Опа! Диаграмата не е намерена.\",\n        unsigned: \"Unsigned\",\n        share: \"Сподели\",\n        unshare: \"Спри споделянето\",\n        copy_link: \"Копирай връзката\",\n        readme: \"README\",\n        failed_to_load: \"Неуспешно зареждане. Уверете се, че връзката е правилна.\",\n        share_info:\n            \"* Споделянето на тази връзка няма да създаде сесия за сътрудничество в реално време.\",\n        show_relationship_labels: \"Покажи етикети на връзките\",\n        docs: \"Документация\",\n        supported_types: \"Поддържани типове файлове:\",\n        bulk_update: \"Масова актуализация\",\n        multiselect: \"Множествен избор\",\n        export_saved_data: \"Експорт на запазени данни\",\n        dbml_view: \"DBML изглед\",\n        tab_view: \"Табличен изглед\",\n        label: \"Етикет\",\n        many_side_label: \"Етикет от страна Много(n)\",\n        version: \"Версия\",\n        versions: \"Версии\",\n        no_saved_versions: \"Няма запазени версии\",\n        record_version: \"Запиши версия\",\n        commited_at: \"Комитнато на\",\n        read_only: \"Само за четене\",\n        continue: \"Продължи\",\n        restore_version: \"Възстанови версия\",\n        restore_warning: \"Зареждането на друга версия ще презапише всички промени.\",\n        return_to_current: \"Върни се към диаграмата\",\n        no_changes_to_record: \"Няма промени за запис\",\n        click_to_view: \"Кликнете за преглед\",\n        load_more: \"Зареди още\",\n        clear_cache: \"Изчисти кеша\",\n        cache_cleared: \"Кешът е изчистен\",\n        failed_to_record_version: \"Неуспешен запис на версия\",\n        failed_to_load_diagram: \"Неуспешно зареждане на диаграма\",\n        see_all: \"Виж всички\",\n        insert_sql: \"Вмъкни SQL\",\n        upload_file: \"Качи файл\",\n    },\n};\n\nexport { bg, bulgarian };\n"
  },
  {
    "path": "src/i18n/locales/bn.js",
    "content": "const bengali = {\n  name: \"Bengali\",\n  native_name: \"বাংলা\",\n  code: \"bn\",\n};\n\nconst bn = {\n  translation: {\n    report_bug: \"বাগ রিপোর্ট করুন\",\n    import: \"ইম্পোর্ট করুন\",\n    inherits: \"উত্তরাধিকার\",\n    merging_column_w_inherited_definition:\n      \"টেবিল '{{tableName}}'-এর '{{fieldName}}' কলাম উত্তরাধিকারসূত্রে একীভূত হবে\",\n    import_from: \"ইম্পোর্ট করুন\",\n    file: \"ফাইল\",\n    new: \"নতুন\",\n    new_window: \"নতুন উইন্ডো\",\n    no_saved_diagrams: \"আপনার কোনো সেভ করা ডায়াগ্রাম নেই\",\n    open: \"ওপেন করুন\",\n    open_recent: \"সাম্প্রতিক ফাইল খুলুন\",\n    save: \"সেভ করুন\",\n    save_as: \"নতুন নামে সেভ করুন\",\n    save_as_template: \"টেমপ্লেট হিসাবে সেভ করুন\",\n    template_saved: \"টেমপ্লেট সেভ হয়েছে!\",\n    rename: \"নাম পরিবর্তন করুন\",\n    delete_diagram: \"ডায়াগ্রাম ডিলিট করুন\",\n    are_you_sure_delete_diagram:\n      \"আপনি কি নিশ্চিত যে আপনি ডায়াগ্রাম মুছে ফেলবেন? একবার মুছে ফেললে আর ফেরত আনা যাবে না।\",\n    oops_smth_went_wrong: \"ওহো! কিছু ভুল হয়েছে।\",\n    import_diagram: \"ডায়াগ্রাম ইম্পোর্ট করুন\",\n    import_from_source: \"SQL থেকে ইম্পোর্ট করুন\",\n    export_as: \"রপ্তানি হিসাবে\",\n    export_source: \"SQL এক্সপোর্ট করুন\",\n    models: \"মডেল\",\n    exit: \"বেরিয়ে যান\",\n    edit: \"এডিট করুন\",\n    undo: \"পূর্বাবস্থা ফিরিয়ে নিন\",\n    redo: \"পুনরায় করুন\",\n    clear: \"মুছে ফেলুন\",\n    are_you_sure_clear: \"আপনি কি নিশ্চিত যে আপনি ডায়াগ্রাম মুছে ফেলবেন? একবার মুছে ফেললে আর ফেরত আনা যাবে না।\",\n    cut: \"কাট করুন\",\n    copy: \"কপি করুন\",\n    paste: \"পেস্ট করুন\",\n    duplicate: \"ডুপ্লিকেট করুন\",\n    delete: \"মুছে ফেলুন\",\n    copy_as_image: \"ছবি হিসাবে কপি করুন\",\n    view: \"ভিউ\",\n    header: \"মেনুবার\",\n    sidebar: \"সাইডবার\",\n    issues: \"সমস্যা\",\n    presentation_mode: \"প্রেজেন্টেশন মোড\",\n    strict_mode: \"স্ট্রিক্ট মোড\",\n    field_details: \"ফিল্ডের বিবরণ\",\n    reset_view: \"ভিউ রিসেট করুন\",\n    show_grid: \"গ্রিড দেখান\",\n    snap_to_grid: \"গ্রিডে স্ন্যাপ করুন\",\n    show_datatype: \"ডেটা টাইপ দেখান\",\n    show_cardinality: \"কার্ডিনালিটি দেখান\",\n    theme: \"থিম\",\n    light: \"লাইট\",\n    dark: \"ডার্ক\",\n    zoom_in: \"জুম ইন করুন\",\n    zoom_out: \"জুম আউট করুন\",\n    fullscreen: \"ফুলস্ক্রিন\",\n    settings: \"সেটিংস\",\n    show_timeline: \"টাইমলাইন দেখান\",\n    autosave: \"অটোসেভ\",\n    panning: \"প্যানিং\",\n    show_debug_coordinates: \"ডিবাগ কোঅর্ডিনেট দেখান\",\n    transform: \"ট্রান্সফর্ম\",\n    viewbox: \"ভিউ বক্স\",\n    cursor_coordinates: \"কার্সার কোঅর্ডিনেট\",\n    coordinate_space: \"স্থান\",\n    coordinate_space_screen: \"স্ক্রিন\",\n    coordinate_space_diagram: \"ডায়াগ্রাম\",\n    table_width: \"টেবিলের প্রস্থ\",\n    language: \"ভাষা\",\n    flush_storage: \"স্টোরেজ ফ্লাশ করুন\",\n    are_you_sure_flush_storage: \"আপনি কি নিশ্চিত যে আপনি স্টোরেজ ফ্লাশ করতে চান? এই পদক্ষেপের ফলে আপনার সকল ডায়াগ্রাম ও কাস্টম টেমপ্লেট স্থায়ীভাবে মুছে যাবে এবং আর ফিরে পাওয়া যাবে না।\",\n    storage_flushed: \"স্টোরেজ ফ্লাশ হয়েছে\",\n    help: \"সাহায্য\",\n    shortcuts: \"শর্টকাট\",\n    ask_on_discord: \"ডিসকর্ডে আমাদের জিজ্ঞাসা করুন\",\n    feedback: \"ফিডব্যাক দিন\",\n    no_changes: \"কোনও পরিবর্তন নেই\",\n    loading: \"লোড হচ্ছে...\",\n    last_saved: \"শেষ সেভ\",\n    saving: \"সেভ হচ্ছে...\",\n    failed_to_save: \"সেভ করতে ব্যর্থ হয়েছে\",\n    fit_window_reset: \"উইন্ডোতে ফিট করুন / রিসেট করুন\",\n    zoom: \"জুম\",\n    add_table: \"টেবিল যোগ করুন\",\n    add_area: \"এরিয়া যোগ করুন\",\n    add_note: \"নোট যোগ করুন\",\n    add_type: \"টাইপ যোগ করুন\",\n    to_do: \"টু-ডু\",\n    tables: \"টেবিল\",\n    relationships: \"রিলেশনশিপগুলি\",\n    subject_areas: \"সাবজেক্ট এরিয়া\",\n    notes: \"নোট\",\n    types: \"টাইপ\",\n    search: \"অনুসন্ধান করুন...\",\n    no_tables: \"কোনও টেবিল নেই\",\n    no_tables_text: \"আপনার ডায়াগ্রামটি তৈরি করা শুরু করুন!\",\n    no_relationships: \"কোনও রিলেশন নেই\",\n    no_relationships_text: \"ফিল্ডগুলো টেনে একে অপরের সঙ্গে সংযুক্ত করুন এবং রিলেশন তৈরি করুন!\",\n    no_subject_areas: \"কোনও সাবজেক্ট এরিয়া নেই\",\n    no_subject_areas_text: \"টেবিলগুলি গ্রুপ করতে সাবজেক্ট এরিয়া যোগ করুন!\",\n    no_notes: \"কোনও নোট নেই\",\n    no_notes_text: \"অতিরিক্ত তথ্য রেকর্ড করার জন্য নোট ব্যবহার করুন\",\n    no_types: \"কোনও টাইপ নেই\",\n    no_types_text: \"আপনার নিজস্ব কাস্টম ডেটা টাইপগুলি তৈরি করুন\",\n    no_issues: \"কোনও সমস্যা সনাক্ত করা যায়নি।\",\n    strict_mode_is_on_no_issues:\n      \"স্ট্রিক্ট মোড বন্ধ রয়েছে, তাই কোনও সমস্যা প্রদর্শিত হবে না।\",\n    name: \"নাম\",\n    type: \"টাইপ\",\n    null: \"নাল\",\n    not_null: \"নাল নয়\",\n    nullable: \"নালযোগ্য\",\n    primary: \"প্রাথমিক\",\n    unique: \"ইউনিক\",\n    autoincrement: \"অটোমেটিক বৃদ্ধি পাবে\",\n    default_value: \"ডিফল্ট ভ্যালু\",\n    check: \"চেক এক্সপ্রেশন\",\n    this_will_appear_as_is:\n      \"*এটি তৈরি করা স্ক্রিপ্টে অপরিবর্তিত অবস্থায় প্রদর্শিত হবে।\",\n    comment: \"মন্তব্য\",\n    add_field: \"ফিল্ড যোগ করুন\",\n    values: \"মান\",\n    size: \"আকার\",\n    precision: \"প্রেসিশন\",\n    set_precision: \"প্রেসিশন সেট করুন: 'আকার, সংখ্যা'\",\n    use_for_batch_input: \"ব্যাচ ইনপুটের জন্য ব্যবহার করুন\",\n    indices: \"ইনডিসেস\",\n    add_index: \"ইনডেক্স যোগ করুন\",\n    select_fields: \"ফিল্ড নির্বাচন করুন\",\n    title: \"শিরোনাম\",\n    not_set: \"সেট করা হয়নি\",\n    foreign: \"ফরেন\",\n    cardinality: \"কার্ডিনালিটি\",\n    on_update: \"আপডেটের সময়\",\n    on_delete: \"ডিলিটের সময়\",\n    swap: \"সোয়াপ\",\n    one_to_one: \"ওয়ান টু ওয়ান\",\n    one_to_many: \"ওয়ান টু ম্যানি\",\n    many_to_one: \"ম্যানি টু ওয়ান\",\n    content: \"বিষয়বস্তু\",\n    types_info:\n      \"এই বৈশিষ্ট্যটি PostgreSQL-এর মত অবজেক্ট-রিলেশনাল DBMS-এর জন্য।\\nযদি MySQL বা MariaDB এর জন্য ব্যবহার করা হয় তবে একটি JSON টাইপ তৈরি হবে সংশ্লিষ্ট json বৈধতা যাচাই সহ।\\nযদি SQLite এর জন্য ব্যবহার করা হয় তবে এটি একটি BLOB এ অনুবাদ হবে।\\nযদি MSSQL এর জন্য ব্যবহার করা হয় তবে প্রথম ক্ষেত্রের একটি টাইপ এলিয়াস তৈরি হবে।\",\n    table_deleted: \"টেবিল মুছে ফেলা হয়েছে\",\n    area_deleted: \"এরিয়া মুছে ফেলা হয়েছে\",\n    note_deleted: \"নোট মুছে ফেলা হয়েছে\",\n    relationship_deleted: \"রিলেশন মুছে ফেলা হয়েছে\",\n    type_deleted: \"টাইপ মুছে ফেলা হয়েছে\",\n    cannot_connect: \"সংযোগ করা যাচ্ছে না, কলামগুলির টাইপ ভিন্ন\",\n    copied_to_clipboard: \"ক্লিপবোর্ডে কপি করা হয়েছে\",\n    create_new_diagram: \"নতুন ডায়াগ্রাম তৈরি করুন\",\n    cancel: \"বাতিল করুন\",\n    open_diagram: \"ডায়াগ্রাম ওপেন করুন\",\n    rename_diagram: \"ডায়াগ্রামের নাম পরিবর্তন করুন\",\n    export: \"এক্সপোর্ট করুন\",\n    export_image: \"ছবি এক্সপোর্ট করুন\",\n    create: \"তৈরি করুন\",\n    confirm: \"নিশ্চিত করুন\",\n    last_modified: \"শেষ সংশোধন\",\n    drag_and_drop_files:\n      \"ফাইলটি এখানে ড্র্যাগ এবং ড্রপ করুন বা আপলোড করতে ক্লিক করুন।\",\n    upload_sql_to_generate_diagrams:\n      \"আপনার টেবিল এবং কলামগুলি স্বয়ংক্রিয়ভাবে তৈরি করতে একটি SQL ফাইল আপলোড করুন।\",\n    overwrite_existing_diagram: \"বিদ্যমান ডায়াগ্রামটি ওভাররাইট করুন\",\n    only_mysql_supported:\n      \"*এখন পর্যন্ত শুধুমাত্র MySQL স্ক্রিপ্ট সাপোর্ট করে।\",\n    blank: \"খালি\",\n    filename: \"ফাইলের নাম\",\n    table_w_no_name: \"নাম ছাড়াই একটি টেবিল ঘোষণা করা হয়েছে\",\n    duplicate_table_by_name: \"'{{tableName}}' নামের টেবিল ডুপ্লিকেট হয়েছে।\",\n    empty_field_name: \"টেবিল '{{tableName}}'-এ `name` ফিল্ডটি খালি আছে\",\n    empty_field_type: \"টেবিল '{{tableName}}'-এ `type` ফিল্ডটি খালি আছে\",\n    no_values_for_field:\n      \"টেবিল '{{tableName}}'-এর '{{fieldName}}' ফিল্ডটি `{{type}}` টাইপের, তবে কোনও ভ্যালু প্রদান করা হয়নি\",\n    default_doesnt_match_type:\n      \"টেবিল '{{tableName}}'-এর '{{fieldName}}' ফিল্ডটির জন্য ডিফল্ট ভ্যালু তার টাইপের সাথে মেলে না\",\n    not_null_is_null:\n      \"টেবিল '{{tableName}}'-এর '{{fieldName}}' ফিল্ডটি NOT NULL তবে ডিফল্ট ভ্যালু NULL\",\n    duplicate_fields:\n      \"টেবিল '{{tableName}}'-এর '{{fieldName}}' নামে ডুপ্লিকেট ফিল্ড আছে\",\n    duplicate_index:\n      \"টেবিল '{{tableName}}'-এর '{{indexName}}' নামে ডুপ্লিকেট ইনডেক্স আছে\",\n    empty_index: \"টেবিল '{{tableName}}'-এর ইনডেক্স কোনও কলামকে ইনডেক্স করে না\",\n    no_primary_key: \"টেবিল '{{tableName}}'-এর কোনও প্রাইমারি কী নেই\",\n    type_with_no_name: \"নাম ছাড়াই একটি টাইপ ডিক্লেয়ার করা হয়েছে\",\n    duplicate_types: \"'{{typeName}}' নামকরণের সাথে ডুপ্লিকেট টাইপ\",\n    type_w_no_fields: \"ফিল্ড ছাড়াই '{{typeName}}' টাইপ ডিক্লেয়ার করা হয়েছে\",\n    empty_type_field_name: \"টাইপ '{{typeName}}'-এ `name` ফিল্ডটি খালি আছে\",\n    empty_type_field_type: \"টাইপ '{{typeName}}'-এ `type` ফিল্ডটি খালি আছে\",\n    no_values_for_type_field:\n      \"টাইপ '{{typeName}}'-এর '{{fieldName}}' ফিল্ডটি `{{type}}` টাইপের, তবে কোনও ভ্যালু প্রদান করা হয়নি\",\n    duplicate_type_fields:\n      \"টাইপ '{{typeName}}'-এর '{{fieldName}}' নামে ডুপ্লিকেট ফিল্ড আছে\",\n    duplicate_reference: \"'{{refName}}' নামে ডুপ্লিকেট রেফারেন্স আছে\",\n    circular_dependency: \"টেবিল '{{refName}}'-এ সার্কুলার ডিপেন্ডেন্সি তৈরি হয়েছে\",\n    timeline: \"টাইমলাইন\",\n    priority: \"অগ্রাধিকার\",\n    none: \"কোনও নয়\",\n    low: \"কম\",\n    medium: \"মাঝারি\",\n    high: \"উচ্চ\",\n    sort_by: \"ক্রমানুসারে সাজান\",\n    my_order: \"আমার আদেশ\",\n    completed: \"সম্পন্ন\",\n    alphabetically: \"বর্ণানুক্রমিকভাবে\",\n    add_task: \"কাজ যোগ করুন\",\n    details: \"বিস্তারিত\",\n    no_tasks: \"আপনার এখনও কোনও কাজ নেই।\",\n    no_activity: \"আপনার এখনও কোনও কার্যকলাপ নেই।\",\n    move_element: \"{{name}} কে {{coords}} তে সরান\",\n    edit_area: \"{{extra}} এরিয়া {{areaName}} এডিট করুন\",\n    delete_area: \"এরিয়া {{areaName}} মুছুন\",\n    edit_note: \"{{extra}} নোট {{noteTitle}} এডিট করুন\",\n    delete_note: \"নোট {{noteTitle}} মুছুন\",\n    edit_table: \"{{extra}} টেবিল {{tableName}} এডিট করুন\",\n    delete_table: \"টেবিল {{tableName}} মুছুন\",\n    edit_type: \"{{extra}} টাইপ {{typeName}} এডিট করুন\",\n    delete_type: \"টাইপ {{typeName}} মুছুন\",\n    add_relationship: \"রিলেশন যোগ করুন\",\n    edit_relationship: \"{{extra}} রিলেশন {{refName}} এডিট করুন\",\n    delete_relationship: \"রিলেশন {{refName}} মুছুন\",\n    not_found: \"খুঁজে পাওয়া যায়নি\",\n    pick_db: \"একটি ডাটাবেস নির্বাচন করুন\",\n    generic: \"জেনেরিক\",\n    generic_description: \"জেনেরিক ডায়াগ্রামগুলি যে কোনও SQL ফ্লেভারে এক্সপোর্ট করা যেতে পারে কিন্তু এতে অল্প কিছু ডেটা টাইপেরই সাপোর্ট আছে।\",\n    enums: \"এনামস\",\n    add_enum: \"এনাম যোগ করুন\",\n    edit_enum: \"{{extra}} এনাম {{enumName}} এডিট করুন\",\n    delete_enum: \"এনাম মুছুন\",\n    enum_w_no_name: \"নাম ছাড়াই একটি এনাম পাওয়া গেছে\",\n    enum_w_no_values: \"কোনও ভ্যালু ছাড়াই এনাম '{{enumName}}' পাওয়া গেছে\",\n    duplicate_enums: \"'{{enumName}}' নামে ডুপ্লিকেট এনামস\",\n    no_enums: \"কোনও এনাম নেই\",\n    no_enums_text: \"এখানে এনামগুলি সংজ্ঞায়িত করুন\",\n    declare_array: \"অ্যারে ঘোষণা করুন\",\n    empty_index_name:\n      \"'{{tableName}}' টেবিলে নাম ছাড়াই একটি ইনডেক্স ঘোষণা করা হয়েছে\",\n    didnt_find_diagram: \"ওহো! ডায়াগ্রামটি পাওয়া যায়নি।\",\n    unsigned: \"আনসাইন্ড\",\n    share: \"শেয়ার করুন\",\n    unshare: \"শেয়ার বন্ধ করুন\",\n    copy_link: \"লিংক কপি করুন\",\n    readme: \"README\",\n    failed_to_load: \"লোড করা যায়নি\",\n    share_info:\n      \"*এই লিঙ্ক শেয়ার করলে লাইভ রিয়েল-টাইম সহযোগিতা সৃষ্টি হবে না।\",\n    show_relationship_labels: \"রিলেশনশিপের লেবেল দেখান\",\n    docs: \"ডকুমেন্টেশন\",\n    supported_types: \"সমর্থিত ফাইল টাইপসমূহ:\",\n    bulk_update: \"বাল্ক আপডেট\",\n    multiselect: \"একাধিক নির্বাচন\",\n    export_saved_data: \"সেভ করা ডেটা এক্সপোর্ট করুন\",\n    dbml_view: \"DBML ভিউ\",\n    tab_view: \"ট্যাব ভিউ\",\n    label: \"লেবেল\",\n    many_side_label: \"Many(n) সাইড লেবেল\",\n    version: \"ভার্সন\",\n    versions: \"ভার্সনসমূহ\",\n    no_saved_versions: \"কোনো সেভ করা ভার্সন নেই\",\n    record_version: \"ভার্সন রেকর্ড করুন\",\n    commited_at: \"কমিট করা হয়েছে\",\n    read_only: \"রিড-অনলি\",\n    continue: \"চালিয়ে যান\",\n    restore_version: \"ভার্সন পুনরুদ্ধার করুন\",\n    restore_warning: \"অন্য ভার্সন লোড করলে যে কোনো পরিবর্তন ওভাররাইট হবে।\",\n    return_to_current: \"বর্তমান ডায়াগ্রামে ফিরে যান\",\n    no_changes_to_record: \"রেকর্ড করার জন্য কোনো পরিবর্তন নেই\",\n    click_to_view: \"দেখতে ক্লিক করুন\",\n    load_more: \"আরও লোড করুন\",\n    clear_cache: \"ক্যাশ পরিষ্কার করুন\",\n    cache_cleared: \"ক্যাশ পরিষ্কার করা হয়েছে\",\n    failed_to_record_version: \"ভার্সন রেকর্ড করতে ব্যর্থ হয়েছে\",\n    failed_to_load_diagram: \"ডায়াগ্রাম লোড করতে ব্যর্থ হয়েছে\",\n    see_all: \"সব দেখুন\",\n  },\n};\n\nexport { bn, bengali };\n"
  },
  {
    "path": "src/i18n/locales/cz.js",
    "content": "const czech = {\n  name: \"Czech\",\n  native_name: \"Česko\",\n  code: \"cz\",\n};\n\nconst cz = {\n  translation: {\n    report_bug: \"Nahlásit chybu\",\n    import: \"Importovat\",\n    import_from: \"Importovat z\",\n    file: \"Soubor\",\n    new: \"Nový\",\n    new_window: \"Nové okno\",\n    open: \"Otevřít\",\n    save: \"Uložit\",\n    save_as: \"Uložit jako\",\n    save_as_template: \"Uložit jako šablonu\",\n    template_saved: \"Šablona uložena!\",\n    rename: \"Přejmenovat\",\n    delete_diagram: \"Smazat diagram\",\n    are_you_sure_delete_diagram:\n      \"Opravdu chcete smazat tento diagram? Tato operace je nevratná.\",\n    oops_smth_went_wrong: \"Jejda! Něco se pokazilo.\",\n    import_diagram: \"Importní diagram\",\n    import_from_source: \"Import z SQL\",\n    export_as: \"Exportovat jako\",\n    export_source: \"zdroj exportu\",\n    models: \"Modelky\",\n    exit: \"Výstup\",\n    edit: \"Upravit\",\n    undo: \"Vrátit zpět\",\n    redo: \"Předělat\",\n    clear: \"čistý\",\n    are_you_sure_clear:\n      \"Opravdu chcete vymazat diagram? To je nevratné.\",\n    cut: \"Střih\",\n    copy: \"Kopie\",\n    paste: \"Vložit\",\n    duplicate: \"Duplikát\",\n    delete: \"Odstranit\",\n    copy_as_image: \"Kopírovat jako obrázek\",\n    view: \"Pohled\",\n    header: \"Nabídkový panel\",\n    sidebar: \"Postranní panel\",\n    issues: \"Problémy\",\n    presentation_mode: \"Prezentační režim\",\n    strict_mode: \"Přísný režim\",\n    field_details: \"Podrobnosti pole\",\n    reset_view: \"Obnovit zobrazení\",\n    show_grid: \"Zobrazit mřížku\",\n    show_datatype: \"Zobrazit datový typ\",\n    show_cardinality: \"Ukažte kardinalitu\",\n    theme: \"Téma\",\n    light: \"Světlo\",\n    dark: \"Tmavý\",\n    zoom_in: \"Přiblížit\",\n    zoom_out: \"Oddálit\",\n    fullscreen: \"Celá obrazovka\",\n    settings: \"Nastavení\",\n    show_timeline: \"Zobrazit časovou osu\",\n    autosave: \"Automatické ukládání\",\n    panning: \"Panašování\",\n    show_debug_coordinates: \"Zobrazit ladicí souřadnice\",\n    transform: \"Transformovat\",\n    viewbox: \"Zobrazit box\",\n    cursor_coordinates: \"Souřadnice kurzoru\",\n    coordinate_space: \"Prostor\",\n    coordinate_space_screen: \"Obrazovka\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Šířka stolu\",\n    language: \"Jazyk\",\n    flush_storage: \"Splachovací úložiště\",\n    are_you_sure_flush_storage:\n      \"Jste si jisti, že chcete úložiště propláchnout? Tím se nenávratně odstraní všechny vaše diagramy a vlastní šablony.\",\n    storage_flushed: \"Úložiště propláchnuto\",\n    help: \"Pomoc\",\n    shortcuts: \"Zkratky\",\n    ask_on_discord: \"Zeptejte se nás na Discord\",\n    feedback: \"Zpětná vazba\",\n    no_changes: \"Žádné změny\",\n    loading: \"Načítání...\",\n    last_saved: \"Naposledy uloženo\",\n    saving: \"Úspora...\",\n    failed_to_save: \"Nepodařilo se uložit\",\n    fit_window_reset: \"Fit okno / Resetovat\",\n    zoom: \"Přiblížení\",\n    add_table: \"Přidat tabulku\",\n    add_area: \"Přidat oblast\",\n    add_note: \"Přidat poznámku\",\n    add_type: \"Přidat typ\",\n    to_do: \"Úkoly k provedení\",\n    tables: \"Tabulky\",\n    relationships: \"Vztahy\",\n    subject_areas: \"Oblasti předmětu\",\n    notes: \"Poznámky\",\n    types: \"Typy\",\n    search: \"Vyhledávání...\",\n    no_tables: \"Žádné stoly\",\n    no_tables_text: \"Začněte vytvářet svůj diagram!\",\n    no_relationships: \"Žádné vztahy\",\n    no_relationships_text: \"Přetažením propojte pole a vytvořte vztahy!\",\n    no_subject_areas: \"Žádné tematické oblasti\",\n    no_subject_areas_text: \"Přidejte tematické oblasti do skupinových tabulek!\",\n    no_notes: \"Žádné poznámky\",\n    no_notes_text: \"Použijte poznámky k zaznamenání dalších informací\",\n    no_types: \"Žádné typy\",\n    no_types_text: \"Vytvořte si vlastní typy dat\",\n    no_issues: \"Nebyly zjištěny žádné problémy.\",\n    strict_mode_is_on_no_issues:\n      \"Přísný režim je vypnutý, takže se nebudou zobrazovat žádné problémy.\",\n    name: \"Jméno\",\n    type: \"Typ\",\n    null: \"Null\",\n    not_null: \"Není nulový\",\n    nullable: \"Nullable\",\n    primary: \"Primární\",\n    unique: \"Unikátní\",\n    autoincrement: \"Autoinkrementace\",\n    default_value: \"Výchozí\",\n    check: \"Zkontrolujte výraz\",\n    this_will_appear_as_is: \"*To se objeví ve vygenerovaném skriptu tak, jak je.\",\n    comment: \"Komentář\",\n    add_field: \"Přidat pole\",\n    values: \"Hodnoty\",\n    size: \"Velikost\",\n    precision: \"Přesnost\",\n    set_precision: \"Nastavit přesnost: 'velikost, číslice'\",\n    use_for_batch_input: \"Použijte , pro dávkové zadání\",\n    indices: \"Indexy\",\n    add_index: \"Přidat index\",\n    select_fields: \"Vybraná pole\",\n    title: \"Titul\",\n    not_set: \"Nenastaveno\",\n    foreign: \"Zahraniční\",\n    cardinality: \"Kardinalita\",\n    on_update: \"Při aktualizaci\",\n    on_delete: \"Při smazání\",\n    swap: \"Výměna\",\n    one_to_one: \"Jedna ku jedné\",\n    one_to_many: \"Jeden k mnoha\",\n    many_to_one: \"Mnoho k jednomu\",\n    content: \"Obsah\",\n    types_info:\n      \"Tato funkce je určena pro objektově-relační DBMS, jako je PostgreSQL.\\nPři použití pro MySQL nebo MariaDB bude vygenerován typ JSON s odpovídající kontrolou platnosti json.\\nPokud je použito pro SQLite, bude přeloženo na BLOB.\\nPokud je použito pro MSSQL, bude vygenerován alias typu prvního pole.\",\n    table_deleted: \"Tabulka vymazána\",\n    area_deleted: \"Oblast smazána\",\n    note_deleted: \"Poznámka smazána\",\n    relationship_deleted: \"Vztah smazán\",\n    type_deleted: \"Typ smazán\",\n    cannot_connect: \"Nelze se připojit, sloupce mají různé typy\",\n    copied_to_clipboard: \"Zkopírováno do schránky\",\n    create_new_diagram: \"Vytvořte nový diagram\",\n    cancel: \"Zrušit\",\n    open_diagram: \"Otevřete diagram\",\n    rename_diagram: \"Přejmenovat diagram\",\n    export: \"Vývozní\",\n    export_image: \"Export obrázku\",\n    create: \"Vytvořit\",\n    confirm: \"Potvrdit\",\n    last_modified: \"Naposledy upraveno\",\n    drag_and_drop_files: \"Přetáhněte soubor sem nebo jej nahrajte kliknutím.\",\n    upload_sql_to_generate_diagrams:\n      \"Nahrajte soubor sql pro automatické generování tabulek a sloupců.\",\n    overwrite_existing_diagram: \"Přepsat existující diagram\",\n    only_mysql_supported:\n      \"*V současné době je podporováno načítání pouze skriptů MySQL.\",\n    blank: \"Prázdný\",\n    filename: \"Název souboru\",\n    table_w_no_name: \"Deklarována tabulka bez názvu\",\n    duplicate_table_by_name: \"Duplicitní tabulka podle názvu '{{tableName}}'\",\n    empty_field_name: \"Prázdné pole `name` v tabulce '{{tableName}}'\",\n    empty_field_type: \"Prázdné pole `type` v tabulce '{{tableName}}'\",\n    no_values_for_field:\n      \"'{{fieldName}}' pole tabulky '{{tableName}}' je typu `{{type}}` ale nebyly zadány žádné hodnoty\",\n    default_doesnt_match_type:\n      \"Výchozí hodnota pro pole '{{fieldName}}' v tabulce '{{tableName}}' neodpovídá svému typu\",\n    not_null_is_null:\n      \"'{{fieldName}}' pole tabulky '{{tableName}}' NENÍ NULL, ale má výchozí hodnotu NULL\",\n    duplicate_fields:\n      \"Duplicitní pole tabulky podle názvu '{{fieldName}}' v tabulce '{{tableName}}'\",\n    duplicate_index:\n      \"Duplicitní index podle názvu '{{indexName}}' v tabulce '{{tableName}}'\",\n    empty_index: \"Index v tabulce '{{tableName}}' neindexuje žádné sloupce\",\n    no_primary_key: \"Tabulka '{{tableName}}' nemá primární klíč\",\n    type_with_no_name: \"Deklarován typ bez názvu\",\n    duplicate_types: \"Duplicitní typy podle názvu '{{typeName}}'\",\n    type_w_no_fields: \"Deklarován prázdný typ '{{typeName}}' bez polí\",\n    empty_type_field_name: \"Prázdné pole `name` v typu '{{typeName}}'\",\n    empty_type_field_type: \"Prázdné pole `type` v typu '{{typeName}}'\",\n    no_values_for_type_field:\n      \"'{{fieldName}}' pole typu '{{typeName}}' je typu `{{type}}` ale nebyly zadány žádné hodnoty\",\n    duplicate_type_fields:\n      \"Duplikujte pole typu podle názvu '{{fieldName}}' v typu '{{typeName}}'\",\n    duplicate_reference: \"Duplicitní odkaz podle názvu '{{refName}}'\",\n    circular_dependency: \"Kruhová závislost zahrnující tabulku '{{refName}}'\",\n    timeline: \"Časová osa\",\n    priority: \"Priorita\",\n    none: \"Žádný\",\n    low: \"Nízký\",\n    medium: \"Střední\",\n    high: \"Vysoký\",\n    sort_by: \"Seřadit podle\",\n    my_order: \"Moje objednávka\",\n    completed: \"Dokončeno\",\n    alphabetically: \"Abecedně\",\n    add_task: \"Přidat úkol\",\n    details: \"Podrobnosti\",\n    no_tasks: \"Zatím nemáte žádné úkoly.\",\n    no_activity: \"Zatím nemáte žádnou aktivitu.\",\n    move_element: \"Pohyb {{name}} na {{coords}}\",\n    edit_area: \"{{extra}} Upravit oblast {{areaName}}\",\n    delete_area: \"Smazat oblast {{areaName}}\",\n    edit_note: \"{{extra}} Upravit poznámku {{noteTitle}}\",\n    delete_note: \"Smazat poznámku {{noteTitle}}\",\n    edit_table: \"{{extra}} Upravit tabulku {{tableName}}\",\n    delete_table: \"Smazat tabulku {{tableName}}\",\n    edit_type: \"{{extra}} Upravit typ {{typeName}}\",\n    delete_type: \"Smazat typ {{typeName}}\",\n    add_relationship: \"Přidat vztah\",\n    edit_relationship: \"{{extra}} Upravit vztah {{refName}}\",\n    delete_relationship: \"Smazat vztah {{refName}}\",\n    not_found: \"Nenalezeno\",\n    pick_db: \"Vyberte databázi\",\n    generic: \"Obecný\",\n    generic_description:\n      \"Obecné diagramy lze exportovat do libovolného jazyka SQL, ale podporují jen několik datových typů.\",\n    enums: \"enum\",\n    add_enum: \"Přidat enum\",\n    edit_enum: \"{{extra}} Upravit enum {{enumName}}\",\n    delete_enum: \"Smazat enum\",\n    enum_w_no_name: \"Nalezen enum bez jména\",\n    enum_w_no_values: \"Nalezeno enum '{{enumName}}' bez hodnot\",\n    duplicate_enums: \"Duplicitní enums se jménem '{{enumName}}'\",\n    no_enums: \"Žádné enums\",\n    no_enums_text: \"Zde definujte enums\",\n    declare_array: \"Deklarace pole\",\n    empty_index_name: \"Deklarován index bez názvu v tabulce '{{tableName}}'\",\n    didnt_find_diagram: \"Ups! Nenašel jsem diagram.\",\n    unsigned: \"Nepodepsaný\",\n    share: \"Podíl\",\n    unshare: \"Zrušit sdílení\",\n    copy_link: \"Zkopírujte odkaz\",\n    readme: \"README\",\n    failed_to_load: \"Načtení se nezdařilo. Ujistěte se, že je odkaz správný.\",\n    share_info:\n      \"* Sdílením tohoto odkazu nevznikne živá relace spolupráce v reálném čase.\",\n    show_relationship_labels: \"Zobrazit štítky vztahů\",\n    docs: \"Docs\",\n    supported_types: \"Podporované typy souborů:\",\n    bulk_update: \"Hromadná aktualizace\",\n    multiselect: \"Vícenásobný výběr\",\n    export_saved_data: \"Export uložených dat\",\n    dbml_view: \"Zobrazení DBML\",\n    tab_view: \"Zobrazení karet\",\n    label: \"Štítek\",\n    many_side_label: \"Štítek na straně mnoho(n)\",\n    version: \"Verze\",\n    versions: \"Verze\",\n    no_saved_versions: \"Žádné uložené verze\",\n    record_version: \"Zaznamenat verzi\",\n    commited_at: \"Potvrzeno v\",\n    read_only: \"Pouze pro čtení\",\n    continue: \"Pokračovat\",\n    restore_version: \"Obnovit verzi\",\n    restore_warning: \"Načtení jiné verze přepíše všechny změny.\",\n    return_to_current: \"Návrat k diagramu\",\n    no_changes_to_record: \"Žádné změny k záznamu\",\n    click_to_view: \"Kliknutím zobrazíte\",\n    load_more: \"Načíst další\",\n    clear_cache: \"Vymazat mezipaměť\",\n    cache_cleared: \"Mezipaměť vymazána\",\n    failed_to_record_version: \"Nepodařilo se zaznamenat verzi\",\n    failed_to_load_diagram: \"Nepodařilo se načíst diagram\",\n    see_all: \"Zobrazit vše\",\n    insert_sql: \"Vložit SQL\",\n    upload_file: \"Nahrát soubor\",\n    enum_deleted: \"Enum smazán\",\n  },\n};\n\nexport { cz, czech };\n"
  },
  {
    "path": "src/i18n/locales/da.js",
    "content": "const danish = {\n  name: \"Danish\",\n  native_name: \"Dansk\",\n  code: \"da\",\n};\n\nconst da = {\n  translation: {\n    report_bug: \"Rapportér en fejl\",\n    import: \"Importér\",\n    inherits: \"Arver\",\n    merging_column_w_inherited_definition:\n      \"Kolonne '{{fieldName}}' i tabel '{{tableName}}' med arvet definition vil blive flettet\",\n    import_from: \"Importér fra\",\n    file: \"Fil\",\n    new: \"Ny\",\n    new_window: \"Nyt vindue\",\n    no_saved_diagrams: \"Du har ingen gemte diagrammer\",\n    open: \"Åben\",\n    open_recent: \"Åbn seneste\",\n    save: \"Gem\",\n    save_as: \"Gem som\",\n    save_as_template: \"Gem som skabelon\",\n    template_saved: \"Skabelon gemt!\",\n    rename: \"Omdøb\",\n    delete_diagram: \"Slet diagram\",\n    are_you_sure_delete_diagram:\n      \"Er du sikker på at du vil slette dette diagram? Denne handling er irreversibel.\",\n    oops_smth_went_wrong: \"Ups! Noget gik galt.\",\n    import_diagram: \"Importér diagram\",\n    import_from_source: \"Importér fra SQL\",\n    export_as: \"Eksportér som\",\n    export_source: \"Eksportér SQL\",\n    models: \"Modeller\",\n    exit: \"Afslut\",\n    edit: \"Redigér\",\n    undo: \"Fortryd\",\n    redo: \"Gentag\",\n    clear: \"Ryd\",\n    are_you_sure_clear:\n      \"Er du sikker på at du vil rydde diagrammet? Denne handling er irreversibel.\",\n    cut: \"Klip\",\n    copy: \"Kopiér\",\n    paste: \"Indsæt\",\n    duplicate: \"Duplikér\",\n    delete: \"Slet\",\n    copy_as_image: \"Kopiér som billede\",\n    view: \"Visning\",\n    header: \"Menubjælke\",\n    sidebar: \"Sidebjælke\",\n    issues: \"Problemer\",\n    presentation_mode: \"Præsentations tilstand\",\n    strict_mode: \"Streng tilstand\",\n    field_details: \"Felt detaljer\",\n    reset_view: \"Nulstil visning\",\n    show_grid: \"Vis gitter\",\n    snap_to_grid: \"Fastgør til gitter\",\n    show_datatype: \"Vis datatype\",\n    show_cardinality: \"Vis kardinalitet\",\n    theme: \"Tema\",\n    light: \"Lyst\",\n    dark: \"Mørkt\",\n    zoom_in: \"Zoom ind\",\n    zoom_out: \"Zoom ud\",\n    fullscreen: \"Fuld skærm\",\n    settings: \"Indstillinger\",\n    show_timeline: \"Vis tidslinje\",\n    autosave: \"Gem automatisk\",\n    panning: \"Panorering\",\n    show_debug_coordinates: \"Vis debug koordinater\",\n    transform: \"Transformér\",\n    viewbox: \"Visningsboks\",\n    cursor_coordinates: \"Markør koordinater\",\n    coordinate_space: \"Rum\",\n    coordinate_space_screen: \"Skærm\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Tabel bredde\",\n    language: \"Sprog\",\n    flush_storage: \"Tøm lagring\",\n    are_you_sure_flush_storage:\n      \"Er du sikker på at du vil tømme lagringen? Dette gør at alle dine diagrammer og individuelle skabeloner bliver slettet irreversibelt\",\n    storage_flushed: \"Lagring tømt\",\n    help: \"Hjælp\",\n    shortcuts: \"Genveje\",\n    ask_on_discord: \"Spørg os på Discord\",\n    feedback: \"Feedback\",\n    no_changes: \"Ingen ændringer\",\n    loading: \"Loader...\",\n    last_saved: \"Sidst gemt\",\n    saving: \"Gemmer...\",\n    failed_to_save: \"Gem fejlede\",\n    fit_window_reset: \"Tilpas vindue / Nulstil\",\n    zoom: \"Zoom\",\n    add_table: \"Tilføj tabel\",\n    add_area: \"Tilføj område\",\n    add_note: \"Tilføj note\",\n    add_type: \"Tilføj type\",\n    to_do: \"To-do\",\n    tables: \"Tabeller\",\n    relationships: \"Forhold\",\n    subject_areas: \"Emne områder\",\n    notes: \"Noter\",\n    types: \"Typer\",\n    search: \"Søg...\",\n    no_tables: \"Ingen tabeller\",\n    no_tables_text: \"Begynd at bygge dit diagram!\",\n    no_relationships: \"Ingen forhold\",\n    no_relationships_text: \"Træk for at forbinde felter og dan forhold!\",\n    no_subject_areas: \"Ingen emne områder\",\n    no_subject_areas_text: \"Tilføj emne områder for at gruppere tabeller!\",\n    no_notes: \"Ingen noter\",\n    no_notes_text: \"Brug noter for at registrere ekstra info\",\n    no_types: \"Ingen typer\",\n    no_types_text: \"Lav dine egne tilpassede data typer\",\n    no_issues: \"Ingen problemer blev opdaget.\",\n    strict_mode_is_on_no_issues:\n      \"Streng tilstand er slået fra, så ingen problemer vil blive vist.\",\n    name: \"Navn\",\n    type: \"Type\",\n    null: \"Nul\",\n    not_null: \"Ikke nul\",\n    nullable: \"Kan være nul\",\n    primary: \"Primær\",\n    unique: \"Unik\",\n    autoincrement: \"Auto-inkrementel\",\n    default_value: \"Standardværdi\",\n    check: \"Tjek udtryk\",\n    this_will_appear_as_is: \"*Dette vil fremstå i det generede script som det er.\",\n    comment: \"Kommentar\",\n    add_field: \"Tilføj felt\",\n    values: \"Værdier\",\n    size: \"Størrelse\",\n    precision: \"Præcision\",\n    set_precision: \"Sæt præcision: 'størrelse, cifre'\",\n    use_for_batch_input: \"Brug , for samlet indtastning\",\n    indices: \"Indekser\",\n    add_index: \"Tilføj indeks\",\n    select_fields: \"Vælg felter\",\n    title: \"Titel\",\n    not_set: \"Ikke sat\",\n    foreign: \"Fremmed\",\n    cardinality: \"Kardinalitet\",\n    on_update: \"På opdater\",\n    on_delete: \"På slet\",\n    swap: \"Swap\",\n    one_to_one: \"En til en\",\n    one_to_many: \"En til mange\",\n    many_to_one: \"Mange til en\",\n    content: \"Indhold\",\n    types_info:\n      \"Denne feature er ment til objekt-relationelle DBMSer ligesom PostgreSQL.\\\\nHvis brugt til MySQL eller MariaDB, vil en JSON type blive genereret med tilsvarende JSON validerings-tjek.\\\\nHvis brugt til SQLite, vil det blive oversat til en BLOB.\\\\nHvis brugt til MSSQL vil et type-alias til det første felt blive genereret.\",\n    table_deleted: \"Tabel slettet\",\n    area_deleted: \"Område slettet\",\n    note_deleted: \"Note slettet\",\n    relationship_deleted: \"Forhold slettet\",\n    type_deleted: \"Type slettet\",\n    cannot_connect: \"Kan ikke forbinde, kolonnerne har forskellige typer\",\n    copied_to_clipboard: \"Kopiér til clipboard\",\n    create_new_diagram: \"Opret nyt diagram\",\n    cancel: \"Afbryd\",\n    open_diagram: \"Åben diagram\",\n    rename_diagram: \"Omdøb diagram\",\n    export: \"Eksportér\",\n    export_image: \"Eksportér billede\",\n    create: \"Opret\",\n    confirm: \"Bekræft\",\n    last_modified: \"Sidst ændret\",\n    drag_and_drop_files: \"Træk og drop filen her eller klik for at uploade.\",\n    upload_sql_to_generate_diagrams:\n      \"Upload en sql fil for at auto-generere dine tabeller og kolonner.\",\n    overwrite_existing_diagram: \"Overskriv eksisterende diagram\",\n    only_mysql_supported:\n      \"*For tiden er det kun MySQL scripts der er understøttet.\",\n    blank: \"Blank\",\n    filename: \"Filnavn\",\n    table_w_no_name: \"Erklærede en tabel med intet navn\",\n    duplicate_table_by_name: \"Dupliker tabellen med navnet '{{tableName}}'\",\n    empty_field_name: \"Tomt felt `navn` i tabellen '{{tableName}}'\",\n    empty_field_type: \"Tomt felt `type` i tabellen '{{tableName}}'\",\n    no_values_for_field:\n      \"'{{fieldName}}' felt fra tabellen '{{tableName}}' er af type `{{type}}` men ingen værdi er blevet specificeret\",\n    default_doesnt_match_type:\n      \"Standardværdien for feltet '{{fieldName}}' i tabellen '{{tableName}}' stemmer ikke overens med dens type\",\n    not_null_is_null:\n      \"'{{fieldName}}' felt fra tabellen '{{tableName}}' er IKKE NUL, men har standardværdien NUL\",\n    duplicate_fields:\n      \"Duplikat tabel felter med navn '{{fieldName}}' på tabellen '{{tableName}}'\",\n    duplicate_index:\n      \"Duplikat indeks med navn '{{indexName}}' på tabellen '{{tableName}}'\",\n    empty_index: \"Indeks på tabel '{{tableName}}' indekser ingen kolonner\",\n    no_primary_key: \"Tabel '{{tableName}}' har ingen primær nøgle\",\n    type_with_no_name: \"Erklæret en type med intet navn\",\n    duplicate_types: \"Duplikat typer med navnet '{{typeName}}'\",\n    type_w_no_fields: \"Erklæret en tom type '{{typeName}}' med ingen felter\",\n    empty_type_field_name: \"Tomt felt `navn` på typen '{{typeName}}'\",\n    empty_type_field_type: \"Tomt felt `type` på typen '{{typeName}}'\",\n    no_values_for_type_field:\n      \"'{{fieldName}}' felt af typen '{{typeName}}' er af typen `{{type}}` men ingen værdier er blevet specificeret\",\n    duplicate_type_fields:\n      \"Duplikat type felter med navnet '{{fieldName}}' på typen '{{typeName}}'\",\n    duplicate_reference: \"Duplikat reference med navnet '{{refName}}'\",\n    circular_dependency: \"Cirkulær afhængighed involveret tabel '{{refName}}'\",\n    timeline: \"Tidslinje\",\n    priority: \"Prioritet\",\n    none: \"Ingen\",\n    low: \"Lav\",\n    medium: \"Middel\",\n    high: \"Høj\",\n    sort_by: \"Sortér på\",\n    my_order: \"Min prioritering\",\n    completed: \"Færdiggjort\",\n    alphabetically: \"Alfabetisk\",\n    add_task: \"Tilføj opgave\",\n    details: \"Detaljer\",\n    no_tasks: \"Du har ingen opgaver endnu.\",\n    no_activity: \"Du har ingen aktivitet endnu.\",\n    move_element: \"Flyt {{name}} til {{coords}}\",\n    edit_area: \"{{extra}} Redigér område {{areaName}}\",\n    delete_area: \"Slet område {{areaName}}\",\n    edit_note: \"{{extra}} Redigér note {{noteTitle}}\",\n    delete_note: \"Slet note {{noteTitle}}\",\n    edit_table: \"{{extra}} Redigér tabel {{tableName}}\",\n    delete_table: \"Slet tabel {{tableName}}\",\n    edit_type: \"{{extra}} Redigér type {{typeName}}\",\n    delete_type: \"Slet type {{typeName}}\",\n    add_relationship: \"Tilføj forhold\",\n    edit_relationship: \"{{extra}} Redigér forhold {{refName}}\",\n    delete_relationship: \"Slet forhold {{refName}}\",\n    not_found: \"Ikke fundet\",\n    pick_db: \"Vælg en database\",\n    generic: \"Generisk\",\n    generic_description:\n      \"Generiske diagrammer kan eksporteres til enhver SQL-variant, men understøtter få datatyper.\",\n    enums: \"Enums\",\n    add_enum: \"Tilføj enum\",\n    edit_enum: \"{{extra}} Redigér enum {{enumName}}\",\n    delete_enum: \"Slet enum\",\n    enum_w_no_name: \"Fandt enum uden navn\",\n    enum_w_no_values: \"Fandt enum '{{enumName}}' uden værdier\",\n    duplicate_enums: \"Duplikat enums med navnet '{{enumName}}'\",\n    enum_deleted: \"Enum slettet\",\n    no_enums: \"Ingen enums\",\n    no_enums_text: \"Definér enums her\",\n    declare_array: \"Erklær array\",\n    empty_index_name: \"Erklæret et indeks uden navn i tabel '{{tableName}}'\",\n    didnt_find_diagram: \"Ups! Kunne ikke finde diagrammet.\",\n    unsigned: \"Usigneret\",\n    share: \"Del\",\n    unshare: \"Fjern deling\",\n    copy_link: \"Kopiér link\",\n    readme: \"LÆSMIG\",\n    failed_to_load: \"Kunne ikke indlæse. Sørg for at linket er korrekt.\",\n    share_info:\n      \"* Deling af dette link vil ikke oprette en live realtids samarbejdssession.\",\n    show_relationship_labels: \"Vis forholdsetiketter\",\n    docs: \"Dokumentation\",\n    supported_types: \"Understøttede filtyper:\",\n    bulk_update: \"Masseopdatering\",\n    multiselect: \"Flervalg\",\n    export_saved_data: \"Eksportér gemte data\",\n    dbml_view: \"DBML-visning\",\n    tab_view: \"Fanevisning\",\n    label: \"Etiket\",\n    many_side_label: \"Mange(n) side etiket\",\n    version: \"Version\",\n    versions: \"Versioner\",\n    no_saved_versions: \"Ingen gemte versioner\",\n    record_version: \"Registrér version\",\n    commited_at: \"Committet den\",\n    read_only: \"Skrivebeskyttet\",\n    continue: \"Fortsæt\",\n    restore_version: \"Gendan version\",\n    restore_warning: \"Indlæsning af en anden version vil overskrive alle ændringer.\",\n    return_to_current: \"Vend tilbage til diagram\",\n    no_changes_to_record: \"Ingen ændringer at registrere\",\n    click_to_view: \"Klik for at se\",\n    load_more: \"Indlæs mere\",\n    clear_cache: \"Ryd cache\",\n    cache_cleared: \"Cache ryddet\",\n    failed_to_record_version: \"Kunne ikke registrere version\",\n    failed_to_load_diagram: \"Kunne ikke indlæse diagram\",\n    see_all: \"Se alle\",\n    insert_sql: \"Indsæt SQL\",\n    upload_file: \"Upload fil\",\n  },\n};\n\nexport { da, danish };\n"
  },
  {
    "path": "src/i18n/locales/de.js",
    "content": "const german = {\n  name: \"German\",\n  native_name: \"Deutsch\",\n  code: \"de\",\n};\n\nconst de = {\n  translation: {\n    report_bug: \"Einen Fehler melden\",\n    import: \"Importieren\",\n    import_from: \"Importieren\",\n    file: \"Datei\",\n    new: \"Neu\",\n    new_window: \"Neues Fenster\",\n    open: \"Öffnen\",\n    save: \"Speichern\",\n    save_as: \"Speichern unter\",\n    save_as_template: \"Als Vorlage speichern\",\n    template_saved: \"Vorlage gespeichert!\",\n    rename: \"Umbenennen\",\n    delete_diagram: \"Diagramm löschen\",\n    are_you_sure_delete_diagram:\n      \"Möchten Sie dieses Diagramm wirklich löschen? Dieser Vorgang kann nicht rückgängig gemacht werden.\",\n    oops_smth_went_wrong: \"Hoppla! Etwas ist schief gelaufen.\",\n    import_diagram: \"Diagramm importieren\",\n    import_from_source: \"Von SQL importieren\",\n    export_as: \"Exportieren als\",\n    export_source: \"SQL exportieren\",\n    models: \"Modelle\",\n    exit: \"Beenden\",\n    edit: \"Bearbeiten\",\n    undo: \"Rückgängig\",\n    redo: \"Wiederherstellen\",\n    clear: \"Leeren\",\n    are_you_sure_clear:\n      \"Möchten Sie das Diagramm wirklich leeren? Dieser Vorgang kann nicht rückgängig gemacht werden.\",\n    cut: \"Ausschneiden\",\n    copy: \"Kopieren\",\n    paste: \"Einfügen\",\n    duplicate: \"Duplizieren\",\n    delete: \"Löschen\",\n    copy_as_image: \"Als Bild kopieren\",\n    view: \"Ansicht\",\n    header: \"Menüleiste\",\n    sidebar: \"Seitenleiste\",\n    issues: \"Probleme\",\n    presentation_mode: \"Präsentationsmodus\",\n    strict_mode: \"Strikter Modus\",\n    field_details: \"Angaben zum Feld\",\n    reset_view: \"Ansicht zurücksetzen\",\n    show_grid: \"Gitter anzeigen\",\n    show_cardinality: \"Kardinalität anzeigen\",\n    theme: \"Motiv\",\n    light: \"Hell\",\n    dark: \"Dunkel\",\n    zoom_in: \"Heranzoomen\",\n    zoom_out: \"Herauszoomen\",\n    fullscreen: \"Vollbild\",\n    settings: \"Einstellungen\",\n    show_timeline: \"Zeitleiste anzeigen\",\n    autosave: \"Automatisch speichern\",\n    panning: \"Verschieben\",\n    show_debug_coordinates: \"Debug Koordinaten anzeigen\",\n    transform: \"Transformation\",\n    viewbox: \"Anzeigefeld\",\n    cursor_coordinates: \"Cursor Koordinaten\",\n    coordinate_space: \"Achse\",\n    coordinate_space_screen: \"Bildschirm\",\n    coordinate_space_diagram: \"Diagramm\",\n    table_width: \"Tabellenbreite\",\n    language: \"Sprache\",\n    flush_storage: \"Speicher leeren\",\n    are_you_sure_flush_storage:\n      \"Sind Sie sicher, dass Sie den Speicher leeren wollen? Dadurch werden alle Ihre Diagramme und benutzerdefinierten Vorlagen unwiderruflich gelöscht.\",\n    storage_flushed: \"Speicher geleert\",\n    help: \"Hilfe\",\n    shortcuts: \"Tastenkürzel\",\n    ask_on_discord: \"Fragen Sie uns auf Discord\",\n    feedback: \"Feedback\",\n    no_changes: \"Keine Änderungen\",\n    loading: \"Laden...\",\n    last_saved: \"Zuletzt gespeichert\",\n    saving: \"Speichern...\",\n    failed_to_save: \"Speichern fehlgeschlagen\",\n    fit_window_reset: \"Fenster anpassen / Zurücksetzen\",\n    zoom: \"Zoom\",\n    add_table: \"Tabelle hinzufügen\",\n    add_area: \"Bereich hinzufügen\",\n    add_note: \"Notiz hinzufügen\",\n    add_type: \"Typ hinzufügen\",\n    to_do: \"Zu erledigen\",\n    tables: \"Tabellen\",\n    relationships: \"Beziehungen\",\n    subject_areas: \"Themengebiete\",\n    notes: \"Notizen\",\n    types: \"Typen\",\n    search: \"Suchen...\",\n    no_tables: \"Keine Tabellen\",\n    no_tables_text: \"Beginnen Sie mit dem Aufbau Ihres Diagramms!\",\n    no_relationships: \"Keine Beziehungen\",\n    no_relationships_text: \"Ziehen Sie, um Felder zu verbinden und Beziehungen herzustellen!\",\n    no_subject_areas: \"Keine Themenbereiche\",\n    no_subject_areas_text: \"Fügen Sie Themenbereiche zu Gruppentabellen hinzu!\",\n    no_notes: \"Keine Notizen\",\n    no_notes_text: \"Fügen Sie Notizen hinzu, um Ihr Diagramm zu kommentieren!\",\n    no_types: \"Keine Typen\",\n    no_types_text: \"Fügen Sie benutzerdefinierte Typen hinzu!\",\n    no_issues: \"Keine Probleme gefunden.\",\n    strict_mode_is_on_no_issues:\n      \"Der strenge Modus ist ausgeschaltet, es werden keine Probleme angezeigt.\",\n    name: \"Name\",\n    type: \"Typ\",\n    null: \"Null\",\n    not_null: \"Nicht Null\",\n    nullable: \"Null erlaubt\",\n    primary: \"Primär\",\n    unique: \"Einzigartig\",\n    autoincrement: \"Autoinkrement\",\n    default_value: \"Standardwert\",\n    check: \"Ausdruck prüfen\",\n    this_will_appear_as_is: \"*Dies wird im generierten Skript so erscheinen.\",\n    comment: \"Kommentar\",\n    add_field: \"Feld hinzufügen\",\n    values: \"Werte\",\n    size: \"Größe\",\n    precision: \"Präzision\",\n    set_precision: \"Präzision festlegen: (Größe, Ziffern)\",\n    use_for_batch_input: \"Verwenden Sie , für Batch-Input\",\n    indices: \"Indizes\",\n    add_index: \"Index hinzufügen\",\n    select_fields: \"Felder auswählen\",\n    title: \"Titel\",\n    not_set: \"Nicht festgelegt\",\n    foreign: \"Fremd\",\n    cardinality: \"Kardinalität\",\n    on_update: \"Beim Aktualisieren\",\n    on_delete: \"Beim Löschen\",\n    swap: \"Tauschen\",\n    one_to_one: \"Eins zu eins\",\n    one_to_many: \"Eins zu viele\",\n    many_to_one: \"Viele zu eins\",\n    content: \"Inhalt\",\n    types_info:\n      \"Diese Funktion ist für objekt-relationale DBMS wie PostgreSQL gedacht.\\n\" +\n      \"Bei Verwendung für MySQL oder MariaDB wird ein JSON-Typ mit der entsprechenden JSON-Validierungsprüfung erzeugt.\\n\" +\n      \"Bei Verwendung für SQLite wird es in ein BLOB übersetzt.\\n\" +\n      \"Bei der Verwendung für MSSQL wird ein Typ-Alias für das erste Feld erzeugt.\",\n    table_deleted: \"Tabelle gelöscht\",\n    area_deleted: \"Bereich gelöscht\",\n    note_deleted: \"Notiz gelöscht\",\n    relationship_deleted: \"Beziehung gelöscht\",\n    type_deleted: \"Typ gelöscht\",\n    cannot_connect: \"Kann nicht verbinden, die Spalten haben unterschiedliche Typen\",\n    copied_to_clipboard: \"In die Zwischenablage kopiert\",\n    create_new_diagram: \"Neues Diagramm erstellen\",\n    cancel: \"Abbrechen\",\n    open_diagram: \"Diagramm öffnen\",\n    rename_diagram: \"Diagramm umbenennen\",\n    export: \"Exportieren\",\n    export_image: \"Bild exportieren\",\n    create: \"Erstellen\",\n    confirm: \"Bestätigen\",\n    last_modified: \"Zuletzt geändert\",\n    drag_and_drop_files: \"Ziehen Sie die Datei hierher oder klicken Sie, um sie hochzuladen.\",\n    upload_sql_to_generate_diagrams:\n      \"Laden Sie eine SQL-Datei hoch, um Ihre Tabellen und Spalten automatisch zu generieren.\",\n    overwrite_existing_diagram: \"Vorhandenes Diagramm überschreiben\",\n    only_mysql_supported:\n      \"*Vorläufig wird nur das Laden von MySQL-Skripten unterstützt.\",\n    blank: \"Leer\",\n    filename: \"Dateiname\",\n    table_w_no_name: \"Eine Tabelle ohne Namen wurde deklariert\",\n    duplicate_table_by_name: \"Doppelte Tabelle mit dem Namen '{{tableName}}'\",\n    empty_field_name: \"Leeres Feld `name` in der Tabelle '{{tableName}}'\",\n    empty_field_type: \"Leeres Feld `type` in der Tabelle '{{tableName}}'\",\n    no_values_for_field:\n      \"Das Feld '{{fieldName}}' der Tabelle '{{tableName}}' ist vom Typ `{{type}}`, aber es wurden keine Werte angegeben\",\n    default_doesnt_match_type:\n      \"Der Standardwert für das Feld '{{fieldName}}' in der Tabelle '{{tableName}}' entspricht nicht seinem Typ\",\n    not_null_is_null:\n      \"Das Feld '{{fieldName}}' der Tabelle '{{tableName}}' ist NOT NULL, hat aber standardmäßig NULL\",\n    duplicate_fields:\n      \"Doppelte Tabellenfelder mit dem Namen '{{fieldName}}' in der Tabelle '{{tableName}}'\",\n    duplicate_index:\n      \"Doppelter Index mit dem Namen '{{indexName}}' in der Tabelle '{{tableName}}'\",\n    empty_index: \"Der Index in Tabelle '{{tableName}}' indiziert keine Spalten\",\n    no_primary_key: \"Tabelle '{{tableName}}' hat keinen Primärschlüssel\",\n    type_with_no_name: \"Ein Typ ohne Namen wurde deklariert\",\n    duplicate_types: \"Doppelte Typen mit dem Namen '{{typeName}}'\",\n    type_w_no_fields: \"Ein leerer Typ '{{typeName}}' ohne Felder wurde deklariert\",\n    empty_type_field_name: \"Leeres Feld `name` im Typ '{{typeName}}'\",\n    empty_type_field_type: \"Leeres Feld `type` im Typ '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Das Feld '{{fieldName}}' des Typs '{{typeName}}' ist vom Typ `{{type}}`, aber es wurden keine Werte angegeben\",\n    duplicate_type_fields:\n      \"Doppelte Typfelder mit dem Namen '{{fieldName}}' im Typ '{{typeName}}'\",\n    duplicate_reference: \"Doppelte Referenz mit dem Namen '{{refName}}'\",\n    circular_dependency: \"Zirkuläre Abhängigkeit, die Tabelle '{{refName}}' betrifft\",\n    timeline: \"Zeitleiste\",\n    priority: \"Priorität\",\n    none: \"Keine\",\n    low: \"Niedrig\",\n    medium: \"Mittel\",\n    high: \"Hoch\",\n    sort_by: \"Sortieren nach\",\n    my_order: \"Meine Reihenfolge\",\n    completed: \"Abgeschlossen\",\n    alphabetically: \"Alphabetisch\",\n    add_task: \"Aufgabe hinzufügen\",\n    details: \"Details\",\n    no_tasks: \"Sie haben noch keine Aufgaben.\",\n    no_activity: \"Sie haben noch keine Aktivitäten.\",\n    move_element: \"{{name}} nach {{coords}} verschieben\",\n    edit_area: \"{{extra}} Bereich {{areaName}} bearbeiten\",\n    delete_area: \"Bereich {{areaName}} löschen\",\n    edit_note: \"{{extra}} Notiz {{noteTitle}} bearbeiten\",\n    delete_note: \"Notiz {{noteTitle}} löschen\",\n    edit_table: \"{{extra}} Tabelle {{tableName}} bearbeiten\",\n    delete_table: \"Tabelle {{tableName}} löschen\",\n    edit_type: \"{{extra}} Typ {{typeName}} bearbeiten\",\n    delete_type: \"Typ {{typeName}} löschen\",\n    add_relationship: \"Beziehung hinzufügen\",\n    edit_relationship: \"{{extra}} Beziehung {{refName}} bearbeiten\",\n    delete_relationship: \"Beziehung {{refName}} löschen\",\n    not_found: \"Nicht gefunden\",\n    pick_db: \"Wählen Sie eine Datenbank\",\n    generic: \"Generisch\",\n    generic_description:\n      \"Generische Diagramme können nach jedem SQL Dialekt exportiert werden, unterstützen aber nur wenige Datentypen.\",\n    enums: \"Aufzählungen\",\n    add_enum: \"Aufzählung hinzufügen\",\n    edit_enum: \"{{extra}} Aufzählung {{enumName}} bearbeiten\",\n    delete_enum: \"Aufzählung löschen\",\n    enum_w_no_name: \"Aufzählung ohne Namen gefunden\",\n    enum_w_no_values: \"Aufzählung '{{enumName}}' ohne Werte gefunden\",\n    duplicate_enums: \"Doppelte Aufzählungen mit dem Namen '{{enumName}}'\",\n    no_enums: \"Keine Aufzählungen\",\n    no_enums_text: \"Aufzählungen hier definieren\",\n    declare_array: \"Liste deklarieren\",\n    empty_index_name: \"Index ohne Namen in der Tabelle '{{tableName}}' deklariert\",\n    didnt_find_diagram: \"Hoppla! Das Diagramm wurde nicht gefunden.\",\n    unsigned: \"Vorzeichenlos\",\n    share: \"Teilen\",\n    unshare: \"Nicht mehr teilen\",\n    copy_link: \"Link kopieren\",\n    readme: \"README\",\n    failed_to_load: \"Laden fehlgeschlagen. Stellen Sie sicher, das der Link korrekt ist.\",\n    share_info:\n      \"* Das Teilen dieses Links ermöglicht keine Live-Zusammenarbeit in Echtzeit.\",\n    show_relationship_labels: \"Beziehungsbeschriftungen anzeigen\",\n    docs: \"Dokumentation\",\n    supported_types: \"Unterstützte Dateitypen:\",\n    bulk_update: \"Massenänderung\",\n    multiselect: \"Mehrfachauswahl\",\n    export_saved_data: \"Gespeicherte Daten exportieren\",\n    inherits: \"Erbt\",\n    merging_column_w_inherited_definition:\n      \"Spalte '{{fieldName}}' in Tabelle '{{tableName}}' mit geerbter Definition wird zusammengeführt\",\n    no_saved_diagrams: \"Sie haben keine gespeicherten Diagramme\",\n    open_recent: \"Zuletzt geöffnet\",\n    snap_to_grid: \"Am Gitter ausrichten\",\n    show_datatype: \"Datentyp anzeigen\",\n    enum_deleted: \"Aufzählung gelöscht\",\n    dbml_view: \"DBML-Ansicht\",\n    tab_view: \"Tab-Ansicht\",\n    label: \"Beschriftung\",\n    many_side_label: \"Viele(n)-Seite Beschriftung\",\n    version: \"Version\",\n    versions: \"Versionen\",\n    no_saved_versions: \"Keine gespeicherten Versionen\",\n    record_version: \"Version aufzeichnen\",\n    commited_at: \"Übertragen am\",\n    read_only: \"Nur lesen\",\n    continue: \"Fortfahren\",\n    restore_version: \"Version wiederherstellen\",\n    restore_warning: \"Das Laden einer anderen Version überschreibt alle Änderungen.\",\n    return_to_current: \"Zum Diagramm zurückkehren\",\n    no_changes_to_record: \"Keine Änderungen zum Aufzeichnen\",\n    click_to_view: \"Zum Anzeigen klicken\",\n    load_more: \"Mehr laden\",\n    clear_cache: \"Cache leeren\",\n    cache_cleared: \"Cache geleert\",\n    failed_to_record_version: \"Fehler beim Aufzeichnen der Version\",\n    failed_to_load_diagram: \"Fehler beim Laden des Diagramms\",\n    see_all: \"Alle anzeigen\",\n    insert_sql: \"SQL einfügen\",\n    upload_file: \"Datei hochladen\",\n  },\n};\n\nexport { de, german };\n"
  },
  {
    "path": "src/i18n/locales/el.js",
    "content": "const greek = {\n  name: \"Greek\",\n  native_name: \"Ελληνικά\",\n  code: \"el\",\n};\n\n\nconst el = {\n  translation: {\n    report_bug: \"Αναφορά σφάλματος\",\n    import_from: \"Εισαγωγή από\",\n    import: \"Εισαγωγή\",\n    file: \"Αρχείο\",\n    new: \"Νέο\",\n    new_window: \"Νέο παράθυρο\",\n    open: \"Άνοιγμα\",\n    open_recent: \"Άνοιγμα πρόσφατου\",\n    no_saved_diagrams: \"Δεν έχετε αποθηκευμένα διαγράμματα\",\n    save: \"Αποθήκευση\",\n    save_as: \"Αποθήκευση ως\",\n    save_as_template: \"Αποθήκευση ως πρότυπο\",\n    template_saved: \"Το πρότυπο αποθηκεύτηκε!\",\n    rename: \"Μετονομασία\",\n    delete_diagram: \"Διαγραφή διαγράμματος\",\n    are_you_sure_delete_diagram:\n      \"Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το διάγραμμα; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.\",\n    oops_smth_went_wrong: \"Ωχ! Κάτι πήγε στραβά.\",\n    import_diagram: \"Εισαγωγή διαγράμματος\",\n    import_from_source: \"Εισαγωγή από SQL\",\n    export_as: \"Εξαγωγή ως\",\n    export_source: \"Εξαγωγή SQL\",\n    models: \"Μοντέλα\",\n    exit: \"Έξοδος\",\n    edit: \"Επεξεργασία\",\n    undo: \"Αναίρεση\",\n    redo: \"Επανάληψη\",\n    clear: \"Καθαρισμός\",\n    are_you_sure_clear:\n      \"Είστε βέβαιοι ότι θέλετε να καθαρίσετε αυτό το διάγραμμα; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.\",\n    cut: \"Αποκοπή\",\n    copy: \"Αντιγραφή\",\n    paste: \"Επικόλληση\",\n    duplicate: \"Δημιουργία αντιγράφου\",\n    delete: \"Διαγραφή\",\n    copy_as_image: \"Αντιγραφή ως εικόνα\",\n    view: \"Προβολή\",\n    header: \"Γραμμή μενού\",\n    sidebar: \"Πλευρική στήλη\",\n    issues: \"Προβλήματα\",\n    presentation_mode: \"Λειτουργία παρουσίασης\",\n    strict_mode: \"Αυστηρή λειτουργία\",\n    field_details: \"Λεπτομέρειες πεδίου\",\n    reset_view: \"Επαναφορά προβολής\",\n    show_grid: \"Εμφάνιση πλέγματος\",\n    snap_to_grid: \"Ευθυγράμμιση στο πλέγμα\",\n    show_datatype: \"Εμφάνιση τύπου δεδομένων\",\n    show_cardinality: \"Εμφάνιση καρδινικότητας\",\n    theme: \"Θέμα\",\n    light: \"Φωτεινό\",\n    dark: \"Σκούρο\",\n    zoom_in: \"Σύμπτυξη (Zoom in)\",\n    zoom_out: \"Συρρίκνωση (Zoom out)\",\n    fullscreen: \"Πλήρης οθόνη\",\n    settings: \"Ρυθμίσεις\",\n    show_timeline: \"Εμφάνιση χρονολογίου\",\n    autosave: \"Αυτόματη αποθήκευση\",\n    panning: \"Μετακίνηση\",\n    show_debug_coordinates: \"Εμφάνιση συντεταγμένων αποσφαλμάτωσης\",\n    transform: \"Μετασχηματισμός\",\n    viewbox: \"Πεδίο προβολής\",\n    cursor_coordinates: \"Συντεταγμένες δρομέα\",\n    coordinate_space: \"Χώρος\",\n    coordinate_space_screen: \"Οθόνη\",\n    coordinate_space_diagram: \"Διάγραμμα\",\n    table_width: \"Πλάτος πίνακα\",\n    language: \"Γλώσσα\",\n    flush_storage: \"Εκκαθάριση αποθήκευσης\",\n    are_you_sure_flush_storage:\n      \"Είστε βέβαιοι ότι θέλετε να εκκαθαρίσετε την αποθήκευση; Αυτό θα διαγράψει οριστικά όλα τα διαγράμματά σας και τα προσαρμοσμένα πρότυπα.\",\n    storage_flushed: \"Η αποθήκευση εκκαθαρίστηκε\",\n    help: \"Βοήθεια\",\n    shortcuts: \"Συντομεύσεις\",\n    ask_on_discord: \"Ρωτήστε μας στο Discord\",\n    feedback: \"Ανατροφοδότηση\",\n    no_changes: \"Δεν υπάρχουν αλλαγές\",\n    loading: \"Φόρτωση...\",\n    last_saved: \"Τελευταία αποθήκευση\",\n    saving: \"Αποθήκευση...\",\n    failed_to_save: \"Αποτυχία αποθήκευσης\",\n    fit_window_reset: \"Προσαρμογή παραθύρου / Επαναφορά\",\n    zoom: \"Ζουμ\",\n    add_table: \"Προσθήκη πίνακα\",\n    add_area: \"Προσθήκη περιοχής\",\n    add_note: \"Προσθήκη σημείωσης\",\n    add_type: \"Προσθήκη τύπου\",\n    to_do: \"Εκκρεμεί\",\n    tables: \"Πίνακες\",\n    relationships: \"Σχέσεις\",\n    subject_areas: \"Περιοχές θεμάτων\",\n    notes: \"Σημειώσεις\",\n    types: \"Τύποι\",\n    search: \"Αναζήτηση...\",\n    no_tables: \"Δεν υπάρχουν πίνακες\",\n    no_tables_text: \"Ξεκινήστε να δημιουργείτε το διάγραμμά σας!\",\n    no_relationships: \"Δεν υπάρχουν σχέσεις\",\n    no_relationships_text: \"Συνδέστε πεδία για να δημιουργήσετε σχέσεις!\",\n    no_subject_areas: \"Δεν υπάρχουν περιοχές θεμάτων\",\n    no_subject_areas_text: \"Προσθέστε περιοχές θεμάτων για να ομαδοποιήσετε πίνακες!\",\n    no_notes: \"Δεν υπάρχουν σημειώσεις\",\n    no_notes_text: \"Χρησιμοποιήστε σημειώσεις για πρόσθετες πληροφορίες\",\n    no_types: \"Δεν υπάρχουν τύποι\",\n    no_types_text: \"Δημιουργήστε τους δικούς σας προσαρμοσμένους τύπους δεδομένων\",\n    no_issues: \"Δεν βρέθηκαν προβλήματα.\",\n    strict_mode_is_on_no_issues:\n      \"Η αυστηρή λειτουργία είναι ενεργοποιημένη, επομένως δεν θα εμφανιστούν τα προβλήματα.\",\n    name: \"Όνομα\",\n    type: \"Τύπος\",\n    null: \"Null\",\n    not_null: \"Not null\",\n    primary: \"Πρωτεύον\",\n    unique: \"Μοναδικό\",\n    autoincrement: \"Αυτοαύξηση\",\n    default_value: \"Προεπιλογή\",\n    check: \"Έκφραση ελέγχου\",\n    this_will_appear_as_is: \"*Αυτό θα εμφανιστεί όπως είναι στο παραγόμενο σκριπτάκι.\",\n    comment: \"Σχόλιο\",\n    add_field: \"Προσθήκη πεδίου\",\n    values: \"Τιμές\",\n    size: \"Μέγεθος\",\n    precision: \"Ακρίβεια\",\n    set_precision: \"Ορίστε ακρίβεια: (μέγεθος, ψηφία)\",\n    use_for_batch_input: \"Χρησιμοποιήστε για παρτίδα εισόδου\",\n    indices: \"Δείκτες\",\n    add_index: \"Προσθήκη δείκτη\",\n    select_fields: \"Επιλογή πεδίων\",\n    title: \"Τίτλος\",\n    not_set: \"Μη ορισμένο\",\n    foreign: \"Ξένο\",\n    cardinality: \"Καρδινικότητα\",\n    on_update: \"Κατά την ενημέρωση\",\n    on_delete: \"Κατά τη διαγραφή\",\n    swap: \"Ανταλλαγή\",\n    one_to_one: \"Ένα προς ένα\",\n    one_to_many: \"Ένα προς πολλά\",\n    many_to_one: \"Πολλά προς ένα\",\n    content: \"Περιεχόμενο\",\n    types_info:\n      \"Αυτή η λειτουργία είναι για αντικειμενοσχεσιακά DBMS όπως το PostgreSQL.\\nΣε MySQL/MariaDB θα παραχθεί τύπος JSON με αντίστοιχο έλεγχο εγκυρότητας.\\nΣε SQLite θα μετατραπεί σε BLOB.\\nΣε MSSQL θα παραχθεί alias τύπου για το πρώτο πεδίο.\",\n    table_deleted: \"Ο πίνακας διαγράφηκε\",\n    area_deleted: \"Η περιοχή διαγράφηκε\",\n    note_deleted: \"Η σημείωση διαγράφηκε\",\n    relationship_deleted: \"Η σχέση διαγράφηκε\",\n    type_deleted: \"Ο τύπος διαγράφηκε\",\n    cannot_connect: \"Δεν είναι δυνατή η σύνδεση — διαφορετικοί τύποι στηλών\",\n    copied_to_clipboard: \"Αντιγράφηκε στο πρόχειρο\",\n    create_new_diagram: \"Δημιουργία νέου διαγράμματος\",\n    cancel: \"Ακύρωση\",\n    open_diagram: \"Άνοιγμα διαγράμματος\",\n    rename_diagram: \"Μετονομασία διαγράμματος\",\n    export: \"Εξαγωγή\",\n    export_image: \"Εξαγωγή εικόνας\",\n    create: \"Δημιουργία\",\n    confirm: \"Επιβεβαίωση\",\n    last_modified: \"Τελευταία τροποποίηση\",\n    drag_and_drop_files:\n      \"Σύρετε και αποθέστε αρχεία εδώ ή κάντε κλικ για να τα ανεβάσετε.\",\n    upload_sql_to_generate_diagrams:\n      \"Ανεβάστε ένα αρχείο SQL για να δημιουργηθούν αυτόματα οι πίνακες και οι στήλες σας.\",\n    overwrite_existing_diagram: \"Αντικατάσταση υπάρχοντος διαγράμματος\",\n    only_mysql_supported: \"*Αυτή τη στιγμή υποστηρίζονται μόνο φορτωμένα MySQL scripts.\",\n    blank: \"Κενό\",\n    filename: \"Όνομα αρχείου\",\n    table_w_no_name: \"Δηλώθηκε πίνακας χωρίς όνομα\",\n    duplicate_table_by_name: \"Διπλότυπος πίνακας με όνομα '{{tableName}}'\",\n    empty_field_name: \"Κενό όνομα πεδίου στον πίνακα '{{tableName}}'\",\n    empty_field_type: \"Κενός τύπος πεδίου στον πίνακα '{{tableName}}'\",\n    no_values_for_field:\n      \"Το πεδίο '{{fieldName}}' του πίνακα '{{tableName}}' έχει τύπο '{{type}}' αλλά δεν ορίστηκαν τιμές\",\n    default_doesnt_match_type:\n      \"Η προεπιλεγμένη τιμή του πεδίου '{{fieldName}}' στον πίνακα '{{tableName}}' δεν ταιριάζει με τον τύπο του\",\n    not_null_is_null:\n      \"Το πεδίο '{{fieldName}}' στον πίνακα '{{tableName}}' έχει NOT NULL αλλά προεπιλεγμένη τιμή NULL\",\n    duplicate_fields:\n      \"Διπλότυπα πεδία με όνομα '{{fieldName}}' στον πίνακα '{{tableName}}'\",\n    duplicate_index:\n      \"Διπλότυπος δείκτης με όνομα '{{indexName}}' στον πίνακα '{{tableName}}'\",\n    empty_index:\n      \"Ο δείκτης στον πίνακα '{{tableName}}' δεν περιλαμβάνει καμία στήλη\",\n    no_primary_key: \"Ο πίνακας '{{tableName}}' δεν έχει πρωτεύον κλειδί\",\n    type_with_no_name: \"Δηλώθηκε τύπος χωρίς όνομα\",\n    duplicate_types: \"Διπλότυποι τύποι με όνομα '{{typeName}}'\",\n    type_w_no_fields: \"Δηλώθηκε τύπος '{{typeName}}' χωρίς πεδία\",\n    empty_type_field_name: \"Κενό όνομα πεδίου στον τύπο '{{typeName}}'\",\n    empty_type_field_type: \"Κενός τύπος πεδίου στον τύπο '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Το πεδίο '{{fieldName}}' του τύπου '{{typeName}}' έχει τύπο '{{type}}' αλλά δεν ορίστηκαν τιμές\",\n    duplicate_type_fields:\n      \"Διπλότυπα πεδία με όνομα '{{fieldName}}' στον τύπο '{{typeName}}'\",\n    duplicate_reference: \"Διπλότυπη αναφορά με όνομα '{{refName}}'\",\n    circular_dependency: \"Κυκλική εξάρτηση στον πίνακα '{{refName}}'\",\n    timeline: \"Χρονοδιάγραμμα\",\n    priority: \"Προτεραιότητα\",\n    none: \"Καμία\",\n    low: \"Χαμηλή\",\n    medium: \"Μέτρια\",\n    high: \"Υψηλή\",\n    sort_by: \"Ταξινόμηση κατά\",\n    my_order: \"Δική μου σειρά\",\n    completed: \"Ολοκληρώθηκε\",\n    alphabetically: \"Αλφαβητικά\",\n    add_task: \"Προσθήκη εργασίας\",\n    details: \"Λεπτομέρειες\",\n    no_tasks: \"Δεν έχετε ακόμα εργασίες.\",\n    no_activity: \"Δεν έχετε ακόμα δραστηριότητα.\",\n    move_element: \"Μετακίνηση {{name}} σε {{coords}}\",\n    edit_area: \"{{extra}} Επεξεργασία περιοχής {{areaName}}\",\n    delete_area: \"Διαγραφή περιοχής {{areaName}}\",\n    edit_note: \"{{extra}} Επεξεργασία σημείωσης {{noteTitle}}\",\n    delete_note: \"Διαγραφή σημείωσης {{noteTitle}}\",\n    edit_table: \"{{extra}} Επεξεργασία πίνακα {{tableName}}\",\n    delete_table: \"Διαγραφή πίνακα {{tableName}}\",\n    edit_type: \"{{extra}} Επεξεργασία τύπου {{typeName}}\",\n    delete_type: \"Διαγραφή τύπου {{typeName}}\",\n    add_relationship: \"Προσθήκη σχέσης\",\n    edit_relationship: \"{{extra}} Επεξεργασία σχέσης {{refName}}\",\n    delete_relationship: \"Διαγραφή σχέσης {{refName}}\",\n    pick_db: \"Επιλογή βάσης δεδομένων\",\n    generic: \"Γενικό\",\n    generic_description:\n      \"Γενικά διαγράμματα μπορούν να εξαχθούν σε οποιαδήποτε διάλεκτο SQL, αλλά δεν υποστηρίζουν όλοι οι τύποι δεδομένων.\",\n    enums: \"Enums\",\n    add_enum: \"Προσθήκη enum\",\n    edit_enum: \"{{extra}} Επεξεργασία enum {{enumName}}\",\n    delete_enum: \"Διαγραφή enum\",\n    enum_w_no_name: \"Βρέθηκε enum χωρίς όνομα\",\n    enum_w_no_values: \"Δεν βρέθηκαν τιμές για το enum '{{enumName}}'\",\n    duplicate_enums: \"Διπλότυπα enums με όνομα '{{enumName}}'\",\n    enum_deleted: \"Το enum διαγράφηκε\",\n    no_enums: \"Δεν υπάρχουν enums\",\n    no_enums_text: \"Ορίστε enums εδώ\",\n    declare_array: \"Δήλωση πίνακα\",\n    empty_index_name: \"Δηλώθηκε δείκτης χωρίς όνομα στον πίνακα '{{tableName}}'\",\n    didnt_find_diagram: \"Ωχ! Δεν βρέθηκε διάγραμμα.\",\n    unsigned: \"Χωρίς πρόσημο\",\n    share: \"Κοινοποίηση\",\n    unshare: \"Αφαίρεση κοινής χρήσης\",\n    copy_link: \"Αντιγραφή συνδέσμου\",\n    readme: \"README\",\n    failed_to_load: \"Αποτυχία φόρτωσης. Βεβαιωθείτε ότι ο σύνδεσμος είναι σωστός.\",\n    share_info:\n      \"* Η κοινοποίηση αυτού του συνδέσμου δεν δημιουργεί συνεδρία συνεργασίας σε πραγματικό χρόνο.\",\n    show_relationship_labels: \"Εμφάνιση ετικετών σχέσης\",\n    docs: \"Τεκμηρίωση\",\n    supported_types: \"Υποστηριζόμενοι τύποι αρχείων:\",\n    bulk_update: \"Μαζική ενημέρωση\",\n    multiselect: \"Πολλαπλή επιλογή\",\n    export_saved_data: \"Εξαγωγή αποθηκευμένων δεδομένων\",\n    dbml_view: \"Προβολή DBML\",\n    tab_view: \"Προβολή καρτελών\",\n    label: \"Ετικέτα\",\n    many_side_label: \"Ετικέτα πλευράς πολλών (n)\",\n    version: \"Έκδοση\",\n    versions: \"Εκδόσεις\",\n    no_saved_versions: \"Δεν υπάρχουν αποθηκευμένες εκδόσεις\",\n    record_version: \"Καταγραφή έκδοσης\",\n    commited_at: \"Δεσμεύτηκε στις\",\n    read_only: \"Μόνο ανάγνωση\",\n    continue: \"Συνέχεια\",\n    restore_version: \"Επαναφορά έκδοσης\",\n    restore_warning: \"Η φόρτωση άλλης έκδοσης θα αντικαταστήσει τυχόν αλλαγές.\",\n    return_to_current: \"Επιστροφή στο διάγραμμα\",\n    no_changes_to_record: \"Δεν υπάρχουν αλλαγές για καταγραφή\",\n    click_to_view: \"Κάντε κλικ για προβολή\",\n    load_more: \"Φόρτωση περισσότερων\",\n    clear_cache: \"Καθαρισμός cache\",\n    cache_cleared: \"Η cache καθαρίστηκε\",\n    failed_to_record_version: \"Αποτυχία καταγραφής έκδοσης\",\n    failed_to_load_diagram: \"Αποτυχία φόρτωσης διαγράμματος\",\n    see_all: \"Δείτε όλα\",\n    insert_sql: \"Εισαγωγή SQL\",\n    upload_file: \"Ανέβασμα αρχείου\",\n    not_found: \"Δεν βρέθηκε\",\n  },\n};\n\nexport { el, greek };"
  },
  {
    "path": "src/i18n/locales/en.js",
    "content": "const english = {\n  name: \"English\",\n  native_name: \"English\",\n  code: \"en\",\n};\n\nconst en = {\n  translation: {\n    report_bug: \"Report a bug\",\n    import: \"Import\",\n    inherits: \"Inherits\",\n    merging_column_w_inherited_definition:\n      \"Column '{{fieldName}}' in table '{{tableName}}' with inherited definition will be merged\",\n    import_from: \"Import from\",\n    file: \"File\",\n    new: \"New\",\n    new_window: \"New window\",\n    no_saved_diagrams: \"You have no saved diagrams\",\n    open: \"Open\",\n    open_recent: \"Open Recent\",\n    save: \"Save\",\n    save_as: \"Save as\",\n    save_as_template: \"Save as template\",\n    template_saved: \"Template saved!\",\n    rename: \"Rename\",\n    delete_diagram: \"Delete diagram\",\n    are_you_sure_delete_diagram:\n      \"Are you sure you want to delete this diagram? This operation is irreversible.\",\n    oops_smth_went_wrong: \"Oops! Something went wrong.\",\n    import_diagram: \"Import diagram\",\n    import_from_source: \"Import from SQL\",\n    export_as: \"Export as\",\n    export_source: \"Export SQL\",\n    models: \"Models\",\n    exit: \"Exit\",\n    edit: \"Edit\",\n    undo: \"Undo\",\n    redo: \"Redo\",\n    clear: \"Clear\",\n    are_you_sure_clear:\n      \"Are you sure you want to clear the diagram? This is irreversible.\",\n    cut: \"Cut\",\n    copy: \"Copy\",\n    paste: \"Paste\",\n    duplicate: \"Duplicate\",\n    delete: \"Delete\",\n    copy_as_image: \"Copy as image\",\n    view: \"View\",\n    header: \"Menubar\",\n    sidebar: \"Sidebar\",\n    issues: \"Issues\",\n    presentation_mode: \"Presentation mode\",\n    strict_mode: \"Strict mode\",\n    field_details: \"Field details\",\n    reset_view: \"Reset view\",\n    show_grid: \"Show grid\",\n    snap_to_grid: \"Snap to grid\",\n    show_datatype: \"Show datatype\",\n    show_cardinality: \"Show cardinality\",\n    theme: \"Theme\",\n    light: \"Light\",\n    dark: \"Dark\",\n    zoom_in: \"Zoom in\",\n    zoom_out: \"Zoom out\",\n    fullscreen: \"Fullscreen\",\n    settings: \"Settings\",\n    show_timeline: \"Show timeline\",\n    autosave: \"Autosave\",\n    panning: \"Panning\",\n    show_debug_coordinates: \"Show debug coordinates\",\n    transform: \"Transform\",\n    viewbox: \"View Box\",\n    cursor_coordinates: \"Cursor Coordinates\",\n    coordinate_space: \"Space\",\n    coordinate_space_screen: \"Screen\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Table width\",\n    language: \"Language\",\n    flush_storage: \"Flush storage\",\n    are_you_sure_flush_storage:\n      \"Are you sure you want to flush the storage? This will irreversibly delete all your diagrams and custom templates.\",\n    storage_flushed: \"Storage flushed\",\n    help: \"Help\",\n    shortcuts: \"Shortcuts\",\n    ask_on_discord: \"Ask us on Discord\",\n    feedback: \"Feedback\",\n    no_changes: \"No changes\",\n    loading: \"Loading...\",\n    last_saved: \"Last saved\",\n    saving: \"Saving...\",\n    failed_to_save: \"Failed to save\",\n    fit_window_reset: \"Fit window / Reset\",\n    zoom: \"Zoom\",\n    add_table: \"Add table\",\n    add_area: \"Add area\",\n    add_note: \"Add note\",\n    add_type: \"Add type\",\n    tables: \"Tables\",\n    relationships: \"Relationships\",\n    subject_areas: \"Subject areas\",\n    notes: \"Notes\",\n    types: \"Types\",\n    search: \"Search...\",\n    no_tables: \"No tables\",\n    no_tables_text: \"Start building your diagram!\",\n    no_relationships: \"No relationships\",\n    no_relationships_text: \"Drag to connect fields and form relationships!\",\n    no_subject_areas: \"No subject areas\",\n    no_subject_areas_text: \"Add subject areas to group tables!\",\n    no_notes: \"No notes\",\n    no_notes_text: \"Use notes to record extra info\",\n    no_types: \"No types\",\n    no_types_text: \"Make your own custom data types\",\n    no_issues: \"No issues were detected.\",\n    strict_mode_is_on_no_issues:\n      \"Strict mode is off so no issues will be displayed.\",\n    name: \"Name\",\n    type: \"Type\",\n    null: \"Null\",\n    not_null: \"Not null\",\n    nullable: \"Nullable\",\n    primary: \"Primary\",\n    unique: \"Unique\",\n    autoincrement: \"Autoincrement\",\n    default_value: \"Default\",\n    check: \"Check expression\",\n    this_will_appear_as_is: \"*This will appear in the generated script as is.\",\n    comment: \"Comment\",\n    add_field: \"Add field\",\n    values: \"Values\",\n    size: \"Size\",\n    precision: \"Precision\",\n    set_precision: \"Set precision: 'size, digits'\",\n    use_for_batch_input: \"Use , for batch input\",\n    indices: \"Indices\",\n    add_index: \"Add index\",\n    select_fields: \"Select fields\",\n    title: \"Title\",\n    not_set: \"Not set\",\n    foreign: \"Foreign\",\n    cardinality: \"Cardinality\",\n    on_update: \"On update\",\n    on_delete: \"On delete\",\n    swap: \"Swap\",\n    one_to_one: \"One to one\",\n    one_to_many: \"One to many\",\n    many_to_one: \"Many to one\",\n    content: \"Content\",\n    types_info:\n      \"This feature is meant for object-relational DBMSs like PostgreSQL.\\nIf used for MySQL or MariaDB a JSON type will be generated with the corresponding json validation check.\\nIf used for SQLite it will be translated to a BLOB.\\nIf used for MSSQL a type alias to the first field will be generated.\",\n    table_deleted: \"Table deleted\",\n    area_deleted: \"Area deleted\",\n    note_deleted: \"Note deleted\",\n    relationship_deleted: \"Relationship deleted\",\n    type_deleted: \"Type deleted\",\n    cannot_connect: \"Cannot connect, the columns have different types\",\n    copied_to_clipboard: \"Copied to clipboard\",\n    create_new_diagram: \"Create new diagram\",\n    cancel: \"Cancel\",\n    open_diagram: \"Open diagram\",\n    rename_diagram: \"Rename diagram\",\n    export: \"Export\",\n    export_image: \"Export image\",\n    create: \"Create\",\n    confirm: \"Confirm\",\n    last_modified: \"Last modified\",\n    drag_and_drop_files: \"Drag and drop the file here or click to upload.\",\n    upload_sql_to_generate_diagrams:\n      \"Upload an sql file to autogenerate your tables and columns.\",\n    overwrite_existing_diagram: \"Overwrite existing diagram\",\n    only_mysql_supported:\n      \"*For the time being loading only MySQL scripts is supported.\",\n    blank: \"Blank\",\n    filename: \"Filename\",\n    table_w_no_name: \"Declared a table with no name\",\n    duplicate_table_by_name: \"Duplicate table by the name '{{tableName}}'\",\n    empty_field_name: \"Empty field `name` in table '{{tableName}}'\",\n    empty_field_type: \"Empty field `type` in table '{{tableName}}'\",\n    no_values_for_field:\n      \"'{{fieldName}}' field of table '{{tableName}}' is of type `{{type}}` but no values have been specified\",\n    default_doesnt_match_type:\n      \"Default value for field '{{fieldName}}' in table '{{tableName}}' does not match its type\",\n    not_null_is_null:\n      \"'{{fieldName}}' field of table '{{tableName}}' is NOT NULL but has default NULL\",\n    duplicate_fields:\n      \"Duplicate table fields by name '{{fieldName}}' in table '{{tableName}}'\",\n    duplicate_index:\n      \"Duplicate index by name '{{indexName}}' in table '{{tableName}}'\",\n    empty_index: \"Index in table '{{tableName}}' indexes no columns\",\n    no_primary_key: \"Table '{{tableName}}' has no primary key\",\n    type_with_no_name: \"Declared a type with no name\",\n    duplicate_types: \"Duplicate types by the name '{{typeName}}'\",\n    type_w_no_fields: \"Declared an empty type '{{typeName}}' with no fields\",\n    empty_type_field_name: \"Empty field `name` in type '{{typeName}}'\",\n    empty_type_field_type: \"Empty field `type` in type '{{typeName}}'\",\n    no_values_for_type_field:\n      \"'{{fieldName}}' field of type '{{typeName}}' is of type `{{type}}` but no values have been specified\",\n    duplicate_type_fields:\n      \"Duplicate type fields by name '{{fieldName}}' in type '{{typeName}}'\",\n    duplicate_reference: \"Duplicate reference by the name '{{refName}}'\",\n    circular_dependency: \"Circular dependency involving table '{{refName}}'\",\n    timeline: \"Timeline\",\n    details: \"Details\",\n    no_activity: \"You have no activity yet.\",\n    move_element: \"Move {{name}} to {{coords}}\",\n    edit_area: \"{{extra}} Edit area {{areaName}}\",\n    delete_area: \"Delete area {{areaName}}\",\n    edit_note: \"{{extra}} Edit note {{noteTitle}}\",\n    delete_note: \"Delete note {{noteTitle}}\",\n    edit_table: \"{{extra}} Edit table {{tableName}}\",\n    delete_table: \"Delete table {{tableName}}\",\n    edit_type: \"{{extra}} Edit type {{typeName}}\",\n    delete_type: \"Delete type {{typeName}}\",\n    add_relationship: \"Add relationship\",\n    edit_relationship: \"{{extra}} Edit relationship {{refName}}\",\n    delete_relationship: \"Delete relationship {{refName}}\",\n    not_found: \"Not found\",\n    pick_db: \"Choose a database\",\n    generic: \"Generic\",\n    generic_description:\n      \"Generic diagrams can be exported to any SQL flavor but support few data types.\",\n    enums: \"Enums\",\n    add_enum: \"Add enum\",\n    edit_enum: \"{{extra}} Edit enum {{enumName}}\",\n    delete_enum: \"Delete enum\",\n    enum_w_no_name: \"Found enum with no name\",\n    enum_w_no_values: \"Found enum '{{enumName}}' with no values\",\n    duplicate_enums: \"Duplicate enums with the name '{{enumName}}'\",\n    enum_deleted: \"Enum deleted\",\n    no_enums: \"No enums\",\n    no_enums_text: \"Define enums here\",\n    declare_array: \"Declare array\",\n    empty_index_name: \"Declared an index with no name in table '{{tableName}}'\",\n    didnt_find_diagram: \"Oops! Didn't find the diagram.\",\n    unsigned: \"Unsigned\",\n    share: \"Share\",\n    unshare: \"Unshare\",\n    copy_link: \"Copy link\",\n    readme: \"README\",\n    failed_to_load: \"Failed to load. Make sure the link is correct.\",\n    share_info:\n      \"* Sharing this link will not create a live real-time collaboration session.\",\n    show_relationship_labels: \"Show relationship labels\",\n    docs: \"Docs\",\n    supported_types: \"Supported file types:\",\n    bulk_update: \"Bulk update\",\n    multiselect: \"Multiselect\",\n    export_saved_data: \"Export saved data\",\n    dbml_view: \"DBML view\",\n    tab_view: \"Tab view\",\n    label: \"Label\",\n    many_side_label: \"Many(n) side label\",\n    version: \"Version\",\n    versions: \"Versions\",\n    no_saved_versions: \"No saved versions\",\n    record_version: \"Record version\",\n    commited_at: \"Commited at\",\n    read_only: \"Read only\",\n    continue: \"Continue\",\n    restore_version: \"Restore version\",\n    restore_warning: \"Loading another version will overwrite any changes.\",\n    return_to_current: \"Return to diagram\",\n    no_changes_to_record: \"No changes to record\",\n    click_to_view: \"Click to view\",\n    load_more: \"Load more\",\n    clear_cache: \"Clear cache\",\n    cache_cleared: \"Cache cleared\",\n    failed_to_record_version: \"Failed to record version\",\n    failed_to_load_diagram: \"Failed to load diagram\",\n    see_all: \"See all\",\n    migrations: \"Migrations\",\n    generate_migration: \"Generate migration\",\n    migration_not_supported_generic:\n      \"Migrations are not supported for generic diagrams.\",\n    no_migration_needed: \"No migration needed\",\n    scripts: \"Scripts\",\n    json_diff: \"JSON diff\",\n    download: \"Download\",\n    insert_sql: \"Insert SQL\",\n    upload_file: \"Upload file\",\n    show_comments: \"Show comments\",\n  },\n};\n\nexport { en, english };\n"
  },
  {
    "path": "src/i18n/locales/es.js",
    "content": "const spanish = {\n  name: \"Spanish\",\n  native_name: \"Español\",\n  code: \"es\",\n};\n\nconst es = {\n  translation: {\n    report_bug: \"Reportar error\",\n    import: \"Importar\",\n    inherits: \"Hereda\",\n    merging_column_w_inherited_definition:\n      \"La columna '{{fieldName}}' en la tabla '{{tableName}}' con definición heredada será fusionada\",\n    import_from: \"Importar desde\",\n    file: \"Archivo\",\n    new: \"Nuevo\",\n    new_window: \"Nueva Ventana\",\n    no_saved_diagrams: \"No tienes diagramas guardados\",\n    open: \"Abrir\",\n    open_recent: \"Abrir reciente\",\n    save: \"Guardar\",\n    save_as: \"Guardar como\",\n    save_as_template: \"Guardar como plantilla\",\n    template_saved: \"Plantilla guardada!\",\n    rename: \"Renombrar\",\n    delete_diagram: \"Eliminar diagrama\",\n    are_you_sure_delete_diagram:\n      \"Estás seguro de que quieres eliminar este diagrama? Esta operación es irreversible.\",\n    oops_smth_went_wrong: \"Ups! Algo salió mal.\",\n    import_diagram: \"Importar diagrama\",\n    import_from_source: \"Importar desde fuente\",\n    export_as: \"Exportar como\",\n    export_source: \"Exportar fuente\",\n    models: \"Modelos\",\n    exit: \"Salir\",\n    edit: \"Editar\",\n    undo: \"Deshacer\",\n    redo: \"Rehacer\",\n    clear: \"limpiar\",\n    are_you_sure_clear:\n      \"Estás seguro de que quieres borrar el diagrama? Esto es irreversible.\",\n    cut: \"Cortar\",\n    copy: \"Copiar\",\n    paste: \"Pegar\",\n    duplicate: \"Duplicar\",\n    delete: \"Eliminar\",\n    copy_as_image: \"Copiar como imagen\",\n    view: \"Ver\",\n    header: \"Encabezado\",\n    sidebar: \"Barra lateral\",\n    issues: \"Problemas\",\n    presentation_mode: \"Modo de presentación\",\n    strict_mode: \"Modo estricto\",\n    field_details: \"Detalles del campo\",\n    reset_view: \"Restablecer vista\",\n    show_grid: \"Mostrar cuadrícula\",\n    snap_to_grid: \"Ajustar a la cuadrícula\",\n    show_datatype: \"Mostrar tipo de datos\",\n    show_cardinality: \"Mostrar cardinalidad\",\n    theme: \"Tema\",\n    light: \"Claro\",\n    dark: \"Oscuro\",\n    zoom_in: \"Acercar\",\n    zoom_out: \"Alejar\",\n    fullscreen: \"Pantalla completa\",\n    settings: \"Configuraciones\",\n    show_timeline: \"Mostrar línea de tiempo\",\n    autosave: \"Guardado automático\",\n    panning: \"Desplazamiento\",\n    show_debug_coordinates: \"Mostrar coordenadas de depuración\",\n    transform: \"Transformar\",\n    viewbox: \"Cuadro de visualización\",\n    cursor_coordinates: \"Coordenadas del cursor\",\n    coordinate_space: \"Espacio de coordenadas\",\n    coordinate_space_screen: \"Espacio de coordenadas de pantalla\",\n    coordinate_space_diagram: \"Espacio de coordenadas de diagrama\",\n    table_width: \"Ancho de la tabla\",\n    language: \"Idioma\",\n    flush_storage: \"Vaciar almacenamiento\",\n    are_you_sure_flush_storage:\n      \"Estás seguro de que quieres vaciar el almacenamiento? Esta operación es irreversible.\",\n    storage_flushed: \"Almacenamiento vaciado!\",\n    help: \"Ayuda\",\n    shortcuts: \"Atajos\",\n    ask_on_discord: \"Pregúntanos en Discord\",\n    feedback: \"Retroalimentación\",\n    no_changes: \"Sin cambios\",\n    loading: \"Cargando...\",\n    last_saved: \"Último guardado\",\n    saving: \"Guardando... \",\n    failed_to_save: \"Error al guardar\",\n    fit_window_reset: \"Ajustar ventana / Restablecer\",\n    zoom: \"Zoom\",\n    add_table: \"Añadir tabla\",\n    add_area: \"Añadir área\",\n    add_note: \"Añadir nota\",\n    add_type: \"Añadir tipo\",\n    to_do: \"Por hacer\",\n    tables: \"Tablas\",\n    relationships: \"Relaciones\",\n    subject_areas: \"Áreas de tema\",\n    notes: \"Notas\",\n    types: \"Tipos\",\n    search: \"Buscar...\",\n    no_tables: \"Sin tablas\",\n    no_tables_text: \"¡Comienza a construir tu diagrama!\",\n    no_relationships: \"Sin relaciones\",\n    no_relationships_text: \"¡Añade relaciones entre tablas!\",\n    no_subject_areas: \"Sin áreas de tema\",\n    no_subject_areas_text: \"¡Añade áreas de tema!\",\n    no_notes: \"Sin notas\",\n    no_notes_text: \"¡Añade notas!\",\n    no_types: \"Sin tipos\",\n    no_types_text: \" ¡Añade tipos!\",\n    no_issues: \" Sin problemas\",\n    strict_mode_is_on_no_issues:\n      \"El modo estricto está activado y no hay problemas.\",\n    name: \"Nombre\",\n    type: \"Tipo\",\n    null: \"Nulo\",\n    not_null: \"No nulo\",\n    nullable: \"Anulable\",\n    primary: \"Primario\",\n    unique: \"Único\",\n    autoincrement: \"Autoincremental\",\n    default_value: \"Valor predeterminado\",\n    check: \"Expresión de verificación\",\n    this_will_appear_as_is: \"*Esto aparecerá en el script generado tal cual.\",\n    comment: \"Comentario\",\n    add_field: \"Agregar campo\",\n    values: \"valores\",\n    size: \"Tamaño\",\n    precision: \"Precisión\",\n    set_precision: \"Establecer precisión: (tamaño, dígitos)\",\n    use_for_batch_input: \"Usar, para entrada por lotes\",\n    indices: \"Índices\",\n    add_index: \"Agregar índice\",\n    select_fields: \"Seleccionar campos\",\n    title: \"Título\",\n    not_set: \"No establecido\",\n    foreign: \"Extranjero\",\n    cardinality: \"Cardinalidad\",\n    on_update: \"Al actualizar\",\n    on_delete: \"Al eliminar\",\n    swap: \"Intercambiar\",\n    one_to_one: \"Uno a uno\",\n    one_to_many: \"Uno a muchos\",\n    many_to_one: \"Muchos a uno\",\n    content: \"Contenido\",\n    types_info:\n      \"Esta característica está destinada a DBMSs objeto-relacionales como PostgreSQL.\\nSi se usa para MySQL o MariaDB, se generará un tipo JSON con la verificación de validación json correspondiente.\\nSi se usa para SQLite, se traducirá a un BLOB.\\nSi se usa para MSSQL, se generará un alias de tipo al primer campo.\",\n    table_deleted: \"Tabla eliminada\",\n    area_deleted: \"Área eliminada\",\n    note_deleted: \"Nota eliminada\",\n    relationship_deleted: \"Relación eliminada\",\n    type_deleted: \"Tipo eliminado\",\n    cannot_connect: \"No se puede conectar, las columnas tienen diferentes tipos\",\n    copied_to_clipboard: \"Copiado al portapapeles\",\n    create_new_diagram: \"Crear nuevo diagrama\",\n    cancel: \"Cancelar\",\n    open_diagram: \"Abrir diagrama\",\n    rename_diagram: \"Renombrar diagrama\",\n    export: \"Exportar\",\n    export_image: \"Exportar imagen\",\n    create: \"Crear\",\n    confirm: \"Confirmar\",\n    last_modified: \"Última modificación\",\n    drag_and_drop_files: \"Arrastra y suelta el archivo aquí o haz clic para subir.\",\n    upload_sql_to_generate_diagrams:\n      \"Sube un archivo sql para autogenerar tus tablas y columnas.\",\n    overwrite_existing_diagram: \"Sobrescribir diagrama existente\",\n    only_mysql_supported:\n      \"*Por el momento, solo se admite la carga de scripts de MySQL.\",\n    blank: \"En blanco\",\n    filename: \"Nombre del archivo\",\n    table_w_no_name: \"Declarada una tabla sin nombre\",\n    duplicate_table_by_name: \"Tabla duplicada con el nombre '{{tableName}}'\",\n    empty_field_name: \"Campo `name` vacío en la tabla '{{tableName}}'\",\n    empty_field_type: \"Campo `type` vacío en la tabla '{{tableName}}'\",\n    no_values_for_field:\n      \"El campo '{{fieldName}}' de la tabla '{{tableName}}' es de tipo `{{type}}` pero no se han especificado valores\",\n    default_doesnt_match_type:\n      \"El valor predeterminado para el campo '{{fieldName}}' en la tabla '{{tableName}}' no coincide con su tipo\",\n    not_null_is_null:\n      \"El campo '{{fieldName}}' de la tabla '{{tableName}}' es NOT NULL pero tiene NULL por defecto\",\n    duplicate_fields:\n      \"Campos de tabla duplicados por nombre '{{fieldName}}' en la tabla '{{tableName}}'\",\n    duplicate_index:\n      \"Índice duplicado por nombre '{{indexName}}' en la tabla '{{tableName}}'\",\n    empty_index: \"Índice en la tabla '{{tableName}}' no indexa columnas\",\n    no_primary_key: \"La tabla '{{tableName}}' no tiene clave primaria\",\n    type_with_no_name: \"Declarado un tipo sin nombre\",\n    duplicate_types: \"Tipos duplicados con el nombre '{{typeName}}'\",\n    type_w_no_fields: \"Declarado un tipo vacío '{{typeName}}' sin campos\",\n    empty_type_field_name: \"Campo `name` vacío en el tipo '{{typeName}}'\",\n    empty_type_field_type: \"Campo `type` vacío en el tipo '{{typeName}}'\",\n    no_values_for_type_field:\n      \"El campo '{{fieldName}}' del tipo '{{typeName}}' es de tipo `{{type}}` pero no se han especificado valores\",\n    duplicate_type_fields:\n      \"Campos de tipo duplicados por nombre '{{fieldName}}' en el tipo '{{typeName}}'\",\n    duplicate_reference: \"Referencia duplicada con el nombre '{{refName}}'\",\n    circular_dependency: \"Dependencia circular involucrando la tabla '{{refName}}'\",\n    timeline: \"Linea del tiempo\",\n    priority: \"Prioridad\",\n    none: \"Ninguno\",\n    low: \"Bajo\",\n    medium: \"Medio\",\n    high: \"Alto\",\n    sort_by: \"Ordenar por\",\n    my_order: \"Mi orden\",\n    completed: \"Completado\",\n    alphabetically: \"Alfabéticamente\",\n    add_task: \"Agregar tarea\",\n    details: \"Detalles\",\n    no_tasks: \"Aún no tienes tareas.\",\n    no_activity: \"Aún no tienes actividad.\",\n    move_element: \"Mover {{name}} a {{coords}}\",\n    edit_area: \"{{extra}} Editar área {{areaName}}\",\n    delete_area: \"Eliminar área {{areaName}}\",\n    edit_note: \"{{extra}} Editar nota {{noteTitle}}\",\n    delete_note: \"Eliminar nota {{noteTitle}}\",\n    edit_table: \"{{extra}} Editar tabla {{tableName}}\",\n    delete_table: \"Eliminar tabla {{tableName}}\",\n    edit_type: \"{{extra}} Editar tipo {{typeName}}\",\n    delete_type: \"Eliminar tipo {{typeName}}\",\n    add_relationship: \"Agregar relación\",\n    edit_relationship: \"{{extra}} Editar relación {{refName}}\",\n    delete_relationship: \"{{enumName}} Eliminar relación {{refName}}\",\n    not_found: \"No encontrado\",\n    pick_db: \"Elegir base de datos\",\n    generic: \"Genérico\",\n    generic_description: \n      \"Los diagramas genéricos se pueden exportar a cualquier formato SQL, pero soportan un número limitado de tipos de datos.\", \n    enums: \"Enumeraciones\",\n    add_enum: \"Añadir enumeración\",\n    edit_enum: \"{{extra}} Editar enumeración {{enumName}}\",\n    delete_enum: \"Borrar enumeración\",\n    enum_w_no_name: \"Encontrado una enumeración sin nombre\",\n    enum_w_no_values: \"Encontrado '{{enumName}}' sin ningún valor\",\n    duplicate_enums: \"Enumeraciones duplicadas con el nombre '{{enumName}}'\",\n    no_enums: \"Sin enumeraciones\",\n    no_enums_text: \"Definir aquí las enumeraciones\",\n    declare_array: \"Declarar array\",\n    empty_index_name: \"Declarado un índice sin nombre en la tabla '{{tableName}}'\",\n    didnt_find_diagram: \"Ups! Diagrama no encontrado.\",\n    unsigned: \"Sin signo\",\n    share: \"Compartir\",\n    unshare: \"Descompartir\",\n    copy_link: \"Copiar enlace\",\n    readme: \"README\",\n    failed_to_load: \"Error al cargar. Asegurate de que el enlace sea correcto.\",\n    share_info: \n      \"* Compartir este enlace no creará una sesión de colaboración en tiempo real.\",\n    show_relationship_labels: \"Mostrar etiquetas de relación\",\n    docs: \"Documentación\",\n    supported_types: \"Tipos de archivo compatibles:\",\n    bulk_update: \"Actualización en bloque\",\n    multiselect: \"Multiselector\",\n    export_saved_data: \"Exportar los datos guardados\",\n    dbml_view: \"Vista DBML\",\n    tab_view: \"Vista de pestañas\",\n    label: \"Etiqueta\",\n    many_side_label: \"Etiqueta del lado muchos(n)\",\n    version: \"Versión\",\n    versions: \"Versiones\",\n    no_saved_versions: \"No hay versiones guardadas\",\n    record_version: \"Grabar versión\",\n    commited_at: \"Confirmado en\",\n    read_only: \"Solo lectura\",\n    continue: \"Continuar\",\n    restore_version: \"Restaurar versión\",\n    restore_warning: \"Cargar otra versión sobrescribirá cualquier cambio.\",\n    return_to_current: \"Volver al diagrama\",\n    no_changes_to_record: \"No hay cambios que grabar\",\n    click_to_view: \"Haz clic para ver\",\n    load_more: \"Cargar más\",\n    clear_cache: \"Limpiar caché\",\n    cache_cleared: \"Caché limpiado\",\n    failed_to_record_version: \"Error al grabar versión\",\n    failed_to_load_diagram: \"Error al cargar diagrama\",\n    see_all: \"Ver todo\",\n  },\n};\n\nexport { es, spanish };\n"
  },
  {
    "path": "src/i18n/locales/fa.js",
    "content": "const persian = {\n  name: \"Persian\",\n  native_name: \"فارسی\",\n  code: \"fa\",\n};\n\nconst fa = {\n  translation: {\n    report_bug: \"گزارش خطا\",\n    import_from: \"وارد کردن\",\n    import: \"وارد کردن\",\n    file: \"فایل\",\n    new: \"جدید\",\n    new_window: \"پنجره جدید\",\n    open: \"باز کردن\",\n    save: \"ذخیره\",\n    save_as: \"ذخیره به عنوان\",\n    save_as_template: \"ذخیره به عنوان الگو\",\n    template_saved: \"الگو ذخیره شد!\",\n    rename: \"تغییر نام\",\n    delete_diagram: \"حذف نمودار\",\n    are_you_sure_delete_diagram:\n      \"آیا مطمئن هستید که می‌خواهید این نمودار را حذف کنید؟ این عملیات غیر قابل برگشت است.\",\n    oops_smth_went_wrong: \"اوه! مشکلی پیش آمد.\",\n    import_diagram: \"وارد کردن نمودار\",\n    import_from_source: \"وارد کردن از SQL\",\n    export_as: \"صادر کردن به عنوان\",\n    export_source: \"صادر کردن SQL\",\n    models: \"مدل‌ها\",\n    exit: \"خروج\",\n    edit: \"ویرایش\",\n    undo: \"واگرد\",\n    redo: \"از نو\",\n    clear: \"پاک کردن\",\n    are_you_sure_clear:\n      \"آیا مطمئن هستید که می‌خواهید نمودار را پاک کنید؟ این عملیات غیر قابل برگشت است.\",\n    cut: \"برش\",\n    copy: \"کپی\",\n    paste: \"چسباندن\",\n    duplicate: \"تکرار\",\n    delete: \"حذف\",\n    copy_as_image: \"کپی به عنوان تصویر\",\n    view: \"مشاهده\",\n    header: \"نوار منو\",\n    sidebar: \"نوار کناری\",\n    issues: \"مشکلات\",\n    presentation_mode: \"حالت ارائه\",\n    strict_mode: \"حالت سختگیرانه\",\n    field_details: \"جزئیات فیلد\",\n    reset_view: \"بازنشانی نما\",\n    show_grid: \"نمایش شبکه\",\n    show_cardinality: \"نمایش کاردینالیته\",\n    theme: \"تم\",\n    light: \"روشن\",\n    dark: \"تاریک\",\n    zoom_in: \"بزرگنمایی\",\n    zoom_out: \"کوچکنمایی\",\n    fullscreen: \"تمام صفحه\",\n    settings: \"تنظیمات\",\n    show_timeline: \"نمایش خط زمانی\",\n    autosave: \"ذخیره خودکار\",\n    panning: \"پانینگ\",\n    table_width: \"عرض جدول\",\n    language: \"زبان\",\n    flush_storage: \"پاک کردن حافظه\",\n    are_you_sure_flush_storage:\n      \"آیا مطمئن هستید که می‌خواهید حافظه را پاک کنید؟ این عمل تمام نمودارها و الگوهای سفارشی شما را به طور غیر قابل برگشت حذف می‌کند.\",\n    storage_flushed: \"حافظه پاک شد\",\n    help: \"راهنما\",\n    shortcuts: \"میانبرها\",\n    ask_on_discord: \"پرسیدن در Discord\",\n    feedback: \"بازخورد\",\n    no_changes: \"بدون تغییرات\",\n    loading: \"در حال بارگذاری...\",\n    last_saved: \"آخرین ذخیره\",\n    saving: \"در حال ذخیره...\",\n    failed_to_save: \"ذخیره‌سازی ناموفق\",\n    fit_window_reset: \"تنظیم پنجره / بازنشانی\",\n    zoom: \"بزرگنمایی\",\n    add_table: \"افزودن جدول\",\n    add_area: \"افزودن ناحیه\",\n    add_note: \"افزودن یادداشت\",\n    add_type: \"افزودن نوع\",\n    to_do: \"برای انجام\",\n    tables: \"جدول‌ها\",\n    relationships: \"روابط\",\n    subject_areas: \"ناحیه‌های موضوعی\",\n    notes: \"یادداشت‌ها\",\n    types: \"نوع‌ها\",\n    search: \"جستجو...\",\n    no_tables: \"بدون جدول\",\n    no_tables_text: \"شروع به ساخت نمودار خود کنید!\",\n    no_relationships: \"بدون رابطه\",\n    no_relationships_text: \"برای اتصال فیلدها و تشکیل روابط بکشید!\",\n    no_subject_areas: \"بدون ناحیه موضوعی\",\n    no_subject_areas_text:\n      \"ناحیه‌های موضوعی را برای گروه‌بندی جدول‌ها اضافه کنید!\",\n    no_notes: \"بدون یادداشت\",\n    no_notes_text: \"از یادداشت‌ها برای ثبت اطلاعات اضافی استفاده کنید\",\n    no_types: \"بدون نوع\",\n    no_types_text: \"نوع داده سفارشی خود را بسازید\",\n    no_issues: \"هیچ مشکلی شناسایی نشد.\",\n    strict_mode_is_on_no_issues:\n      \"حالت سختگیرانه خاموش است بنابراین هیچ مشکلی نمایش داده نخواهد شد.\",\n    name: \"نام\",\n    type: \"نوع\",\n    null: \"خالی\",\n    not_null: \"غیر خالی\",\n    primary: \"اصلی\",\n    unique: \"یگانه\",\n    autoincrement: \"افزایش خودکار\",\n    default_value: \"پیش‌فرض\",\n    check: \"عبارت بررسی\",\n    this_will_appear_as_is:\n      \"*این در اسکریپت تولید شده به همان صورت نمایش داده می‌شود.\",\n    comment: \"نظر\",\n    add_field: \"افزودن فیلد\",\n    values: \"مقادیر\",\n    size: \"اندازه\",\n    precision: \"دقت\",\n    set_precision: \"تنظیم دقت: (اندازه، ارقام)\",\n    use_for_batch_input: \"برای ورودی دسته‌ای از , استفاده کنید\",\n    indices: \"شاخص‌ها\",\n    add_index: \"افزودن شاخص\",\n    select_fields: \"انتخاب فیلدها\",\n    title: \"عنوان\",\n    not_set: \"تنظیم نشده\",\n    foreign: \"خارجی\",\n    cardinality: \"کاردینالیته\",\n    on_update: \"در به‌روزرسانی\",\n    on_delete: \"در حذف\",\n    swap: \"جابجایی\",\n    one_to_one: \"یک به یک\",\n    one_to_many: \"یک به چند\",\n    many_to_one: \"چند به یک\",\n    content: \"محتوا\",\n    types_info:\n      \"این ویژگی برای DBMS‌های شیء‌گرا مانند PostgreSQL طراحی شده است.\\nاگر برای MySQL یا MariaDB استفاده شود، نوع JSON با بررسی اعتبار json متناظر تولید می‌شود.\\nاگر برای SQLite استفاده شود، به BLOB ترجمه می‌شود.\\nاگر برای MSSQL استفاده شود، یک نام مستعار نوع برای فیلد اول تولید می‌شود.\",\n    table_deleted: \"جدول حذف شد\",\n    area_deleted: \"ناحیه حذف شد\",\n    note_deleted: \"یادداشت حذف شد\",\n    relationship_deleted: \"رابطه حذف شد\",\n    type_deleted: \"نوع حذف شد\",\n    cannot_connect: \"اتصال غیر ممکن است، ستون‌ها انواع مختلفی دارند\",\n    copied_to_clipboard: \"به کلیپ‌بورد کپی شد\",\n    create_new_diagram: \"ایجاد نمودار جدید\",\n    cancel: \"لغو\",\n    open_diagram: \"باز کردن نمودار\",\n    rename_diagram: \"تغییر نام نمودار\",\n    export: \"صادر کردن\",\n    export_image: \"صادر کردن تصویر\",\n    create: \"ایجاد\",\n    confirm: \"تأیید\",\n    last_modified: \"آخرین ویرایش\",\n    drag_and_drop_files:\n      \"فایل را اینجا بکشید و رها کنید یا کلیک کنید تا بارگذاری شود.\",\n    upload_sql_to_generate_diagrams:\n      \"یک فایل sql را بارگذاری کنید تا جداول و ستون‌هایتان به‌طور خودکار تولید شوند.\",\n    overwrite_existing_diagram: \"بازنویسی نمودار موجود\",\n    only_mysql_supported:\n      \"*در حال حاضر فقط بارگذاری اسکریپت‌های MySQL پشتیبانی می‌شود.\",\n    blank: \"خالی\",\n    filename: \"نام فایل\",\n    table_w_no_name: \"جدولی بدون نام اعلام شد\",\n    duplicate_table_by_name: \"جدول تکراری با نام '{{tableName}}'\",\n    empty_field_name: \"فیلد خالی name در جدول '{{tableName}}'\",\n    empty_field_type: \"فیلد خالی type در جدول '{{tableName}}'\",\n    no_values_for_field:\n      \"فیلد '{{fieldName}}' جدول '{{tableName}}' از نوع {{type}} است اما هیچ مقداری مشخص نشده است\",\n    default_doesnt_match_type:\n      \"مقدار پیش‌فرض برای فیلد '{{fieldName}}' در جدول '{{tableName}}' با نوع آن مطابقت ندارد\",\n    not_null_is_null:\n      \"فیلد '{{fieldName}}' جدول '{{tableName}}' غیر خالی است اما پیش‌فرض آن خالی است\",\n    duplicate_fields:\n      \"فیلدهای تکراری جدول به نام '{{fieldName}}' در جدول '{{tableName}}'\",\n    duplicate_index:\n      \"شاخص تکراری به نام '{{indexName}}' در جدول '{{tableName}}'\",\n    empty_index: \"شاخص در جدول '{{tableName}}' هیچ ستونی را شاخص نمی‌کند\",\n    no_primary_key: \"جدول '{{tableName}}' کلید اصلی ندارد\",\n    type_with_no_name: \"نوعی بدون نام اعلام شد\",\n    duplicate_types: \"انواع تکراری به نام '{{typeName}}'\",\n    type_w_no_fields: \"نوع خالی '{{typeName}}' بدون فیلد اعلام شد\",\n    empty_type_field_name: \"فیلد `name` خالی در نوع '{{typeName}}'\",\n    empty_type_field_type: \"فیلد `type` خالی در نوع '{{typeName}}'\",\n    no_values_for_type_field:\n      \"'{{fieldName}}' فیلد از نوع '{{typeName}}' از نوع `{{type}}` است اما هیچ مقداری مشخص نشده است\",\n    duplicate_type_fields:\n      \"فیلدهای تکراری نوع با نام '{{fieldName}}' در نوع '{{typeName}}'\",\n    duplicate_reference: \"ارجاع تکراری به نام '{{refName}}'\",\n    circular_dependency: \"وابستگی دورانی شامل جدول '{{refName}}'\",\n    timeline: \"جدول زمانی\",\n    priority: \"اولویت\",\n    none: \"هیچکدام\",\n    low: \"کم\",\n    medium: \"متوسط\",\n    high: \"زیاد\",\n    sort_by: \"مرتب‌سازی بر اساس\",\n    my_order: \"ترتیب من\",\n    completed: \"تکمیل شده\",\n    alphabetically: \"الفبایی\",\n    add_task: \"اضافه کردن کار\",\n    details: \"جزئیات\",\n    no_tasks: \"هنوز کاری ندارید.\",\n    no_activity: \"هنوز فعالیتی ندارید.\",\n    move_element: \"انتقال {{name}} به {{coords}}\",\n    edit_area: \"{{extra}} ویرایش ناحیه {{areaName}}\",\n    delete_area: \"حذف ناحیه {{areaName}}\",\n    edit_note: \"{{extra}} ویرایش یادداشت {{noteTitle}}\",\n    delete_note: \"حذف یادداشت {{noteTitle}}\",\n    edit_table: \"{{extra}} ویرایش جدول {{tableName}}\",\n    delete_table: \"حذف جدول {{tableName}}\",\n    edit_type: \"{{extra}} ویرایش نوع {{typeName}}\",\n    delete_type: \"حذف نوع {{typeName}}\",\n    add_relationship: \"اضافه کردن ارتباط\",\n    edit_relationship: \"{{extra}} ویرایش ارتباط {{refName}}\",\n    delete_relationship: \"حذف ارتباط {{refName}}\",\n    not_found: \"یافت نشد\",\n  },\n};\n\nexport { fa, persian };\n"
  },
  {
    "path": "src/i18n/locales/fi.js",
    "content": "const finnish = {\n  name: \"Finnish\",\n  native_name: \"Suomi\",\n  code: \"fi\",\n};\n\nconst fi = {\n  translation: {\n    report_bug: \"Ilmoita virheestä\",\n    import: \"Tuo\",\n    inherits: \"Perii\",\n    merging_column_w_inherited_definition:\n      \"Sarake '{{fieldName}}' taulussa '{{tableName}}' perityllä määritelmällä yhdistetään\",\n    import_from: \"Tuo kohteesta\",\n    file: \"Tiedosto\",\n    new: \"Uusi\",\n    new_window: \"Uusi ikkuna\",\n    no_saved_diagrams: \"Sinulla ei ole tallennettuja kaavioita\",\n    open: \"Avaa\",\n    open_recent: \"Avaa äskettäin käytetyt\",\n    save: \"Tallenna\",\n    save_as: \"Tallenna nimellä\",\n    save_as_template: \"Tallenna mallipohjana\",\n    template_saved: \"Mallipohja tallennettu!\",\n    rename: \"Nimeä uudelleen\",\n    delete_diagram: \"Poista kaavio\",\n    are_you_sure_delete_diagram:\n      \"Haluatko varmasti poistaa tämän kaavion? Tämä toiminto on peruuttamaton.\",\n    oops_smth_went_wrong: \"Hups! Jotain meni pieleen.\",\n    import_diagram: \"Tuo kaavio\",\n    import_from_source: \"Tuo SQL:stä\",\n    export_as: \"Vie muodossa\",\n    export_source: \"Vie SQL\",\n    models: \"Mallit\",\n    exit: \"Poistu\",\n    edit: \"Muokkaa\",\n    undo: \"Kumoa\",\n    redo: \"Tee uudelleen\",\n    clear: \"Tyhjennä\",\n    are_you_sure_clear:\n      \"Haluatko varmasti tyhjentää kaavion? Tämä on peruuttamaton.\",\n    cut: \"Leikkaa\",\n    copy: \"Kopioi\",\n    paste: \"Liitä\",\n    duplicate: \"Monista\",\n    delete: \"Poista\",\n    copy_as_image: \"Kopioi kuvana\",\n    view: \"Näkymä\",\n    header: \"Valikkopalkki\",\n    sidebar: \"Sivupalkki\",\n    issues: \"Ongelmat\",\n    presentation_mode: \"Esitystila\",\n    strict_mode: \"Tiukka tila\",\n    field_details: \"Kentän tiedot\",\n    reset_view: \"Nollaa näkymä\",\n    show_grid: \"Näytä ruudukko\",\n    snap_to_grid: \"Kiinnitä ruudukkoon\",\n    show_datatype: \"Näytä tietotyyppi\",\n    show_cardinality: \"Näytä kardinaliteetti\",\n    theme: \"Teema\",\n    light: \"Vaalea\",\n    dark: \"Tumma\",\n    zoom_in: \"Lähennä\",\n    zoom_out: \"Loitonna\",\n    fullscreen: \"Koko näyttö\",\n    settings: \"Asetukset\",\n    show_timeline: \"Näytä aikajana\",\n    autosave: \"Automaattinen tallennus\",\n    panning: \"Panorointi\",\n    show_debug_coordinates: \"Näytä debug-koordinaatit\",\n    transform: \"Muunna\",\n    viewbox: \"Näkymälaatikko\",\n    cursor_coordinates: \"Kursorin koordinaatit\",\n    coordinate_space: \"Avaruus\",\n    coordinate_space_screen: \"Näyttö\",\n    coordinate_space_diagram: \"Kaavio\",\n    table_width: \"Taulun leveys\",\n    language: \"Kieli\",\n    flush_storage: \"Tyhjennä tallennustila\",\n    are_you_sure_flush_storage:\n      \"Haluatko varmasti tyhjentää tallennustilan? Tämä poistaa peruuttamattomasti kaikki kaaviosi ja mukautetut mallipohjat.\",\n    storage_flushed: \"Tallennustila tyhjennetty\",\n    help: \"Ohje\",\n    shortcuts: \"Pikanäppäimet\",\n    ask_on_discord: \"Kysy meiltä Discordissa\",\n    feedback: \"Palaute\",\n    no_changes: \"Ei muutoksia\",\n    loading: \"Ladataan...\",\n    last_saved: \"Viimeksi tallennettu\",\n    saving: \"Tallennetaan...\",\n    failed_to_save: \"Tallennus epäonnistui\",\n    fit_window_reset: \"Sovita ikkunaan / Nollaa\",\n    zoom: \"Zoomaa\",\n    add_table: \"Lisää taulu\",\n    add_area: \"Lisää alue\",\n    add_note: \"Lisää muistiinpano\",\n    add_type: \"Lisää tyyppi\",\n    to_do: \"Tehtävälista\",\n    tables: \"Taulut\",\n    relationships: \"Suhteet\",\n    subject_areas: \"Aihealueet\",\n    notes: \"Muistiinpanot\",\n    types: \"Tyypit\",\n    search: \"Hae...\",\n    no_tables: \"Ei tauluja\",\n    no_tables_text: \"Aloita kaaviosi rakentaminen!\",\n    no_relationships: \"Ei suhteita\",\n    no_relationships_text: \"Vedä yhdistääksesi kentät ja muodostaaksesi suhteita!\",\n    no_subject_areas: \"Ei aihealueita\",\n    no_subject_areas_text: \"Lisää aihealueita ryhmitelläksesi tauluja!\",\n    no_notes: \"Ei muistiinpanoja\",\n    no_notes_text: \"Käytä muistiinpanoja tallentaaksesi lisätietoja\",\n    no_types: \"Ei tyyppejä\",\n    no_types_text: \"Luo omia mukautettuja tietotyyppejä\",\n    no_issues: \"Ongelmia ei havaittu.\",\n    strict_mode_is_on_no_issues:\n      \"Tiukka tila on pois päältä, joten ongelmia ei näytetä.\",\n    name: \"Nimi\",\n    type: \"Tyyppi\",\n    null: \"Null\",\n    not_null: \"Ei null\",\n    nullable: \"Null sallittu\",\n    primary: \"Pääavain\",\n    unique: \"Yksilöllinen\",\n    autoincrement: \"Automaattinen kasvatus\",\n    default_value: \"Oletusarvo\",\n    check: \"Tarkistuslauseke\",\n    this_will_appear_as_is: \"*Tämä näkyy luodussa skriptissä sellaisenaan.\",\n    comment: \"Kommentti\",\n    add_field: \"Lisää kenttä\",\n    values: \"Arvot\",\n    size: \"Koko\",\n    precision: \"Tarkkuus\",\n    set_precision: \"Aseta tarkkuus: 'koko, numerot'\",\n    use_for_batch_input: \"Käytä , eräsyötteeseen\",\n    indices: \"Indeksit\",\n    add_index: \"Lisää indeksi\",\n    select_fields: \"Valitse kentät\",\n    title: \"Otsikko\",\n    not_set: \"Ei asetettu\",\n    foreign: \"Viiteavain\",\n    cardinality: \"Kardinaliteetti\",\n    on_update: \"Päivityksessä\",\n    on_delete: \"Poistossa\",\n    swap: \"Vaihda\",\n    one_to_one: \"Yksi yhteen\",\n    one_to_many: \"Yksi moneen\",\n    many_to_one: \"Monta yhteen\",\n    content: \"Sisältö\",\n    types_info:\n      \"Tämä ominaisuus on tarkoitettu objektirelaatiotietokannoille kuten PostgreSQL.\\nJos käytetään MySQL:ää tai MariaDB:tä, luodaan JSON-tyyppi vastaavalla json-validoinnilla.\\nJos käytetään SQLite:a, se käännetään BLOB:ksi.\\nJos käytetään MSSQL:ää, luodaan tyyppialias ensimmäiselle kentälle.\",\n    table_deleted: \"Taulu poistettu\",\n    area_deleted: \"Alue poistettu\",\n    note_deleted: \"Muistiinpano poistettu\",\n    relationship_deleted: \"Suhde poistettu\",\n    type_deleted: \"Tyyppi poistettu\",\n    cannot_connect: \"Ei voida yhdistää, sarakkeilla on eri tyypit\",\n    copied_to_clipboard: \"Kopioitu leikepöydälle\",\n    create_new_diagram: \"Luo uusi kaavio\",\n    cancel: \"Peruuta\",\n    open_diagram: \"Avaa kaavio\",\n    rename_diagram: \"Nimeä kaavio uudelleen\",\n    export: \"Vie\",\n    export_image: \"Vie kuva\",\n    create: \"Luo\",\n    confirm: \"Vahvista\",\n    last_modified: \"Viimeksi muokattu\",\n    drag_and_drop_files: \"Vedä ja pudota tiedosto tähän tai klikkaa ladataksesi.\",\n    upload_sql_to_generate_diagrams:\n      \"Lataa SQL-tiedosto automaattisesti luodaksesi taulut ja sarakkeet.\",\n    overwrite_existing_diagram: \"Korvaa olemassa oleva kaavio\",\n    only_mysql_supported:\n      \"*Tällä hetkellä vain MySQL-skriptien lataaminen on tuettu.\",\n    blank: \"Tyhjä\",\n    filename: \"Tiedostonimi\",\n    table_w_no_name: \"Määritelty taulu ilman nimeä\",\n    duplicate_table_by_name: \"Kaksoiskappale taulusta nimellä '{{tableName}}'\",\n    empty_field_name: \"Tyhjä kentän `nimi` taulussa '{{tableName}}'\",\n    empty_field_type: \"Tyhjä kentän `tyyppi` taulussa '{{tableName}}'\",\n    no_values_for_field:\n      \"'{{fieldName}}' kenttä taulussa '{{tableName}}' on tyyppiä `{{type}}` mutta arvoja ei ole määritelty\",\n    default_doesnt_match_type:\n      \"Oletusarvo kentälle '{{fieldName}}' taulussa '{{tableName}}' ei vastaa sen tyyppiä\",\n    not_null_is_null:\n      \"'{{fieldName}}' kenttä taulussa '{{tableName}}' on NOT NULL mutta oletusarvo on NULL\",\n    duplicate_fields:\n      \"Kaksoiskappale kentistä nimellä '{{fieldName}}' taulussa '{{tableName}}'\",\n    duplicate_index:\n      \"Kaksoiskappale indeksistä nimellä '{{indexName}}' taulussa '{{tableName}}'\",\n    empty_index: \"Indeksi taulussa '{{tableName}}' ei indeksoi sarakkeita\",\n    no_primary_key: \"Taululla '{{tableName}}' ei ole pääavainta\",\n    type_with_no_name: \"Määritelty tyyppi ilman nimeä\",\n    duplicate_types: \"Kaksoiskappale tyypeistä nimellä '{{typeName}}'\",\n    type_w_no_fields: \"Määritelty tyhjä tyyppi '{{typeName}}' ilman kenttiä\",\n    empty_type_field_name: \"Tyhjä kentän `nimi` tyypissä '{{typeName}}'\",\n    empty_type_field_type: \"Tyhjä kentän `tyyppi` tyypissä '{{typeName}}'\",\n    no_values_for_type_field:\n      \"'{{fieldName}}' kenttä tyypissä '{{typeName}}' on tyyppiä `{{type}}` mutta arvoja ei ole määritelty\",\n    duplicate_type_fields:\n      \"Kaksoiskappale kentistä nimellä '{{fieldName}}' tyypissä '{{typeName}}'\",\n    duplicate_reference: \"Kaksoiskappale viitteestä nimellä '{{refName}}'\",\n    circular_dependency: \"Syklinen riippuvuus taulun '{{refName}}' osalta\",\n    timeline: \"Aikajana\",\n    priority: \"Prioriteetti\",\n    none: \"Ei mitään\",\n    low: \"Matala\",\n    medium: \"Keskitaso\",\n    high: \"Korkea\",\n    sort_by: \"Järjestä\",\n    my_order: \"Oma järjestys\",\n    completed: \"Valmis\",\n    alphabetically: \"Aakkosjärjestyksessä\",\n    add_task: \"Lisää tehtävä\",\n    details: \"Yksityiskohdat\",\n    no_tasks: \"Sinulla ei ole vielä tehtäviä.\",\n    no_activity: \"Sinulla ei ole vielä toimintaa.\",\n    move_element: \"Siirrä {{name}} kohtaan {{coords}}\",\n    edit_area: \"{{extra}} Muokkaa aluetta {{areaName}}\",\n    delete_area: \"Poista alue {{areaName}}\",\n    edit_note: \"{{extra}} Muokkaa muistiinpanoa {{noteTitle}}\",\n    delete_note: \"Poista muistiinpano {{noteTitle}}\",\n    edit_table: \"{{extra}} Muokkaa taulua {{tableName}}\",\n    delete_table: \"Poista taulu {{tableName}}\",\n    edit_type: \"{{extra}} Muokkaa tyyppiä {{typeName}}\",\n    delete_type: \"Poista tyyppi {{typeName}}\",\n    add_relationship: \"Lisää suhde\",\n    edit_relationship: \"{{extra}} Muokkaa suhdetta {{refName}}\",\n    delete_relationship: \"Poista suhde {{refName}}\",\n    not_found: \"Ei löytynyt\",\n    pick_db: \"Valitse tietokanta\",\n    generic: \"Yleinen\",\n    generic_description:\n      \"Yleiset kaaviot voidaan viedä mihin tahansa SQL-tyyppiin, mutta ne tukevat vain muutamia tietotyyppejä.\",\n    enums: \"Luettelot\",\n    add_enum: \"Lisää luettelo\",\n    edit_enum: \"{{extra}} Muokkaa luetteloa {{enumName}}\",\n    delete_enum: \"Poista luettelo\",\n    enum_w_no_name: \"Löydetty luettelo ilman nimeä\",\n    enum_w_no_values: \"Löydetty luettelo '{{enumName}}' ilman arvoja\",\n    duplicate_enums: \"Kaksoiskappale luetteloista nimellä '{{enumName}}'\",\n    enum_deleted: \"Luettelo poistettu\",\n    no_enums: \"Ei luetteloita\",\n    no_enums_text: \"Määritä luettelot tässä\",\n    declare_array: \"Määritä taulukko\",\n    empty_index_name: \"Määritelty indeksi ilman nimeä taulussa '{{tableName}}'\",\n    didnt_find_diagram: \"Hups! Kaaviota ei löytynyt.\",\n    unsigned: \"Etumerkitön\",\n    share: \"Jaa\",\n    unshare: \"Poista jako\",\n    copy_link: \"Kopioi linkki\",\n    readme: \"README\",\n    failed_to_load: \"Lataus epäonnistui. Varmista, että linkki on oikein.\",\n    share_info:\n      \"* Tämän linkin jakaminen ei luo live-tapahtumaa reaaliaikaisessa yhteistyössä.\",\n    show_relationship_labels: \"Näytä suhteiden tunnisteet\",\n    docs: \"Dokumentaatio\",\n    supported_types: \"Tuetut tiedostotyypit:\",\n    bulk_update: \"Massapäivitys\",\n    multiselect: \"Monivalinta\",\n    export_saved_data: \"Vie tallennetut tiedot\",\n    dbml_view: \"DBML-näkymä\",\n    tab_view: \"Välilehtinäkymä\",\n    label: \"Tunniste\",\n    many_side_label: \"Monta(n) puolen tunniste\",\n    version: \"Versio\",\n    versions: \"Versiot\",\n    no_saved_versions: \"Ei tallennettuja versioita\",\n    record_version: \"Tallenna versio\",\n    commited_at: \"Tallennettu\",\n    read_only: \"Vain luku\",\n    continue: \"Jatka\",\n    restore_version: \"Palauta versio\",\n    restore_warning: \"Toisen version lataaminen korvaa kaikki muutokset.\",\n    return_to_current: \"Palaa kaavioon\",\n    no_changes_to_record: \"Ei muutoksia tallennettavaksi\",\n    click_to_view: \"Klikkaa nähdäksesi\",\n    load_more: \"Lataa lisää\",\n    clear_cache: \"Tyhjennä välimuisti\",\n    cache_cleared: \"Välimuisti tyhjennetty\",\n    failed_to_record_version: \"Version tallennus epäonnistui\",\n    failed_to_load_diagram: \"Kaavion lataus epäonnistui\",\n    see_all: \"Näytä kaikki\",\n    insert_sql: \"Lisää SQL\",\n    upload_file: \"Lataa tiedosto\",\n  },\n};\n\nexport { fi, finnish };\n\n"
  },
  {
    "path": "src/i18n/locales/fr.js",
    "content": "const french = {\r\n  name: \"French\",\r\n  native_name: \"Français\",\r\n  code: \"fr\",\r\n};\r\n\r\nconst fr = {\r\n  translation: {\r\n    report_bug: \"Signaler un bug\",\r\n    import_from: \"Importer de\",\r\n    import: \"Importer\",\r\n    file: \"Fichier\",\r\n    new: \"Nouveau\",\r\n    new_window: \"Nouvelle fenêtre\",\r\n    open: \"Ouvrir\",\r\n    save: \"Enregistrer\",\r\n    save_as: \"Enregistrer sous\",\r\n    save_as_template: \"Enregistrer en tant que modèle\",\r\n    template_saved: \"Modèle enregistré!\",\r\n    rename: \"Renommer\",\r\n    delete_diagram: \"Supprimer le diagramme\",\r\n    are_you_sure_delete_diagram:\r\n      \"Êtes-vous sûr de vouloir supprimer ce diagramme? Cette action est irréversible.\",\r\n    oops_smth_went_wrong: \"Oups! Quelque chose s'est mal passé.\",\r\n    import_diagram: \"Importer un diagramme\",\r\n    import_from_source: \"Importer depuis SQL\",\r\n    export_as: \"Exporter en tant que\",\r\n    export_source: \"Exporter SQL\",\r\n    models: \"Modèles\",\r\n    exit: \"Sortir\",\r\n    edit: \"Éditer\",\r\n    undo: \"Annuler\",\r\n    redo: \"Rétablir\",\r\n    clear: \"Effacer\",\r\n    are_you_sure_clear:\r\n      \"Êtes-vous sûr de vouloir effacer ce diagramme? Cette action est irréversible.\",\r\n    cut: \"Couper\",\r\n    copy: \"Copier\",\r\n    paste: \"Coller\",\r\n    duplicate: \"Dupliquer\",\r\n    delete: \"Supprimer\",\r\n    copy_as_image: \"Copier en tant qu'image\",\r\n    view: \"Vue\",\r\n    header: \"Barre de menu\",\r\n    sidebar: \"Barre latérale\",\r\n    issues: \"Problèmes\",\r\n    presentation_mode: \"Mode présentation\",\r\n    strict_mode: \"Mode strict\",\r\n    field_details: \"Détails du champ\",\r\n    reset_view: \"Réinitialiser la vue\",\r\n    show_grid: \"Afficher la grille\",\r\n    show_cardinality: \"Afficher la cardinalité\",\r\n    theme: \"Thème\",\r\n    light: \"Clair\",\r\n    dark: \"Sombre\",\r\n    zoom_in: \"Zoom avant\",\r\n    zoom_out: \"Zoom arrière\",\r\n    fullscreen: \"Plein écran\",\r\n    settings: \"Paramètres\",\r\n    show_timeline: \"Afficher la chronologie\",\r\n    autosave: \"Sauvegarde automatique\",\r\n    panning: \"Panoramique\",\r\n    table_width: \"Largeur de la table\",\r\n    language: \"Langue\",\r\n    flush_storage: \"Vider le stockage\",\r\n    are_you_sure_flush_storage:\r\n      \"Êtes-vous sûr de vouloir vider le stockage? Cela supprimera de manière irréversible tous vos diagrammes et modèles personnalisés.\",\r\n    storage_flushed: \"Stockage vidé\",\r\n    help: \"Aide\",\r\n    shortcuts: \"Raccourcis\",\r\n    ask_on_discord: \"Demandez-nous sur Discord\",\r\n    feedback: \"Retour d'information\",\r\n    no_changes: \"Aucun changement\",\r\n    loading: \"Chargement...\",\r\n    last_saved: \"Dernière sauvegarde\",\r\n    saving: \"Enregistrement...\",\r\n    failed_to_save: \"Échec de l'enregistrement\",\r\n    fit_window_reset: \"Ajuster / Réinitialiser la fenêtre\",\r\n    zoom: \"Zoom\",\r\n    add_table: \"Ajouter une table\",\r\n    add_area: \"Ajouter une zone\",\r\n    add_note: \"Ajouter une note\",\r\n    add_type: \"Ajouter un type\",\r\n    to_do: \"À faire\",\r\n    tables: \"Tables\",\r\n    relationships: \"Relations\",\r\n    subject_areas: \"Sujets\",\r\n    notes: \"Notes\",\r\n    types: \"Types\",\r\n    search: \"Rechercher...\",\r\n    no_tables: \"Aucune table\",\r\n    no_tables_text: \"Commencez à créer votre diagramme!\",\r\n    no_relationships: \"Aucune relation\",\r\n    no_relationships_text:\r\n      \"Faites glisser pour connecter les champs et créer des relations!\",\r\n    no_subject_areas: \"Aucune zone de sujet\",\r\n    no_subject_areas_text:\r\n      \"Regroupez les tables en ajoutant des zones de sujet!\",\r\n    no_notes: \"Aucune note\",\r\n    no_notes_text:\r\n      \"Utilisez les notes pour enregistrer des informations supplémentaires\",\r\n    no_types: \"Aucun type\",\r\n    no_types_text: \"Créez vos propres types de données personnalisés\",\r\n    no_issues: \"Aucun problème détecté.\",\r\n    strict_mode_is_on_no_issues:\r\n      \"Le mode strict est désactivé, donc aucun problème ne sera affiché.\",\r\n    name: \"Nom\",\r\n    type: \"Type\",\r\n    null: \"Null\",\r\n    not_null: \"Not Null\",\r\n    primary: \"Primaire\",\r\n    unique: \"Unique\",\r\n    autoincrement: \"Auto-incrément\",\r\n    default_value: \"Valeur par défaut\",\r\n    check: \"Expression de vérification\",\r\n    this_will_appear_as_is: \"*Ceci apparaîtra tel quel dans le script généré.\",\r\n    comment: \"Commentaire\",\r\n    add_field: \"Ajouter un champ\",\r\n    values: \"Valeurs\",\r\n    size: \"Taille\",\r\n    precision: \"Précision\",\r\n    set_precision: \"Définir la précision: (taille, chiffres)\",\r\n    use_for_batch_input: \"Utiliser , pour les entrées par lot\",\r\n    indices: \"Indices\",\r\n    add_index: \"Ajouter un index\",\r\n    select_fields: \"Sélectionner les champs\",\r\n    title: \"Titre\",\r\n    not_set: \"Non défini\",\r\n    foreign: \"Étranger\",\r\n    cardinality: \"Cardinalité\",\r\n    on_update: \"Lors de la mise à jour\",\r\n    on_delete: \"Lors de la suppression\",\r\n    swap: \"Échanger\",\r\n    one_to_one: \"Un à un\",\r\n    one_to_many: \"Un à plusieurs\",\r\n    many_to_one: \"Plusieurs à un\",\r\n    content: \"Contenu\",\r\n    types_info:\r\n      \"Cette fonctionnalité est pour les SGBD orientés objets comme PostgreSQL.\\nSi utilisée avec MySQL ou MariaDB, un type JSON sera généré avec une vérification de validité JSON correspondante.\\nSi utilisée avec SQLite, elle sera convertie en BLOB.\\nSi utilisée avec MSSQL, un alias de type sera généré pour le premier champ.\",\r\n    table_deleted: \"Table supprimée\",\r\n    area_deleted: \"Zone supprimée\",\r\n    note_deleted: \"Note supprimée\",\r\n    relationship_deleted: \"Relation supprimée\",\r\n    type_deleted: \"Type supprimé\",\r\n    cannot_connect:\r\n      \"Impossible de connecter, les types de colonnes sont différents\",\r\n    copied_to_clipboard: \"Copié dans le presse-papiers\",\r\n    create_new_diagram: \"Créer un nouveau diagramme\",\r\n    cancel: \"Annuler\",\r\n    open_diagram: \"Ouvrir le diagramme\",\r\n    rename_diagram: \"Renommer le diagramme\",\r\n    export: \"Exporter\",\r\n    export_image: \"Exporter l'image\",\r\n    create: \"Créer\",\r\n    confirm: \"Confirmer\",\r\n    last_modified: \"Dernière modification\",\r\n    drag_and_drop_files:\r\n      \"Glissez et déposez les fichiers ici ou cliquez pour les télécharger.\",\r\n    upload_sql_to_generate_diagrams:\r\n      \"Téléchargez un fichier SQL pour générer automatiquement vos tables et colonnes.\",\r\n    overwrite_existing_diagram: \"Écraser le diagramme existant\",\r\n    only_mysql_supported:\r\n      \"*Pour le moment, seuls les scripts MySQL peuvent être chargés.\",\r\n    blank: \"Vide\",\r\n    filename: \"Nom du fichier\",\r\n    table_w_no_name: \"Table déclarée sans nom\",\r\n    duplicate_table_by_name: \"Table en double par le nom '{{tableName}}'\",\r\n    empty_field_name: \"Nom de champ vide dans la table '{{tableName}}'\",\r\n    empty_field_type: \"Type de champ vide dans la table '{{tableName}}'\",\r\n    no_values_for_field:\r\n      \"Le champ '{{fieldName}}' de la table '{{tableName}}' a un type `{{type}}` mais aucune valeur n'est spécifiée\",\r\n    default_doesnt_match_type:\r\n      \"La valeur par défaut du champ '{{fieldName}}' de la table '{{tableName}}' ne correspond pas à son type\",\r\n    not_null_is_null:\r\n      \"Le champ '{{fieldName}}' de la table '{{tableName}}' est NOT NULL mais la valeur par défaut est NULL\",\r\n    duplicate_fields:\r\n      \"Champs de table en double nommés '{{fieldName}}' dans la table '{{tableName}}'\",\r\n    duplicate_index:\r\n      \"Index en double nommé '{{indexName}}' dans la table '{{tableName}}'\",\r\n    empty_index: \"Index sans colonnes dans la table '{{tableName}}'\",\r\n    no_primary_key: \"Aucune clé primaire dans la table '{{tableName}}'\",\r\n    type_with_no_name: \"Type déclaré sans nom\",\r\n    duplicate_types: \"Types en double nommés '{{typeName}}'\",\r\n    type_w_no_fields: \"Type déclaré sans champs '{{typeName}}'\",\r\n    empty_type_field_name: \"Nom de champ vide dans le type '{{typeName}}'\",\r\n    empty_type_field_type: \"Type de champ vide dans le type '{{typeName}}'\",\r\n    no_values_for_type_field:\r\n      \"Le champ '{{fieldName}}' du type '{{typeName}}' a un type `{{type}}` mais aucune valeur n'est spécifiée\",\r\n    duplicate_type_fields:\r\n      \"Champs de type en double nommés '{{fieldName}}' dans le type '{{typeName}}'\",\r\n    duplicate_reference: \"Référence en double nommée '{{refName}}'\",\r\n    circular_dependency: \"Dépendance circulaire dans la table '{{refName}}'\",\r\n    timeline: \"Chronologie\",\r\n    priority: \"Priorité\",\r\n    none: \"Aucun\",\r\n    low: \"Faible\",\r\n    medium: \"Moyen\",\r\n    high: \"Élevé\",\r\n    sort_by: \"Trier par\",\r\n    my_order: \"Mon ordre\",\r\n    completed: \"Terminé\",\r\n    alphabetically: \"Alphabétiquement\",\r\n    add_task: \"Ajouter une tâche\",\r\n    details: \"Détails\",\r\n    no_tasks: \"Vous n'avez pas encore de tâches.\",\r\n    no_activity: \"Vous n'avez pas encore d'activité.\",\r\n    move_element: \"Déplacer {{name}} à {{coords}}\",\r\n    edit_area: \"{{extra}} Modifier la zone {{areaName}}\",\r\n    delete_area: \"Supprimer la zone {{areaName}}\",\r\n    edit_note: \"{{extra}} Modifier la note {{noteTitle}}\",\r\n    delete_note: \"Supprimer la note {{noteTitle}}\",\r\n    edit_table: \"{{extra}} Modifier la table {{tableName}}\",\r\n    delete_table: \"Supprimer la table {{tableName}}\",\r\n    edit_type: \"{{extra}} Modifier le type {{typeName}}\",\r\n    delete_type: \"Supprimer le type {{typeName}}\",\r\n    add_relationship: \"Ajouter une relation\",\r\n    edit_relationship: \"{{extra}} Modifier la relation {{refName}}\",\r\n    delete_relationship: \"Supprimer la relation {{refName}}\",\r\n    not_found: \"Non trouvé\",\r\n    readme: \"README\",\r\n  },\r\n};\r\n\r\nexport { fr, french };\r\n"
  },
  {
    "path": "src/i18n/locales/gu.js",
    "content": "const gujarati = {\n  name: \"Gujarati\",\n  native_name: \"ગુજરાતી\",\n  code: \"gu\",\n};\n\nconst gu = {\n  translation: {\n    report_bug: \"બગ રિપોર્ટ કરો\",\n    import: \"આયાત\",\n    inherits: \"વારસામાં મળે છે\",\n    merging_column_w_inherited_definition:\n      \"ટેબલ '{{tableName}}' માં કોલમ '{{fieldName}}' વારસાગત વ્યાખ્યા સાથે મર્જ કરવામાં આવશે\",\n    import_from: \"માંથી આયાત કરો\",\n    file: \"ફાઇલ\",\n    new: \"નવું\",\n    new_window: \"નવી વિંડો\",\n    no_saved_diagrams: \"તમારી પાસે કોઈ સેવ કરેલા ડાયાગ્રામ નથી\",\n    open: \"ખોલો\",\n    open_recent: \"તાજેતરનું ખોલો\",\n    save: \"સેવ\",\n    save_as: \"તરીકે સેવ કરો\",\n    save_as_template: \"ટેમ્પલેટ તરીકે સેવ કરો\",\n    template_saved: \"ટેમ્પલેટ સેવ થઇ ગયું!\",\n    rename: \"નામ બદલો\",\n    delete_diagram: \"ડાયાગ્રામ કાઢી નાંખો\",\n    are_you_sure_delete_diagram:\n      \"શું તમે ખરેખર આ ડાયાગ્રામ કાઢી નાંખવા માંગો છો? આ ક્રિયા અપરિવર્તનીય છે.\",\n    oops_smth_went_wrong: \"અરે! કઈક ખોટું થઇ ગયું.\",\n    import_diagram: \"ડાયાગ્રામ આયાત કરો\",\n    import_from_source: \"SQL થી આયાત કરો\",\n    export_as: \"તરીકે નિકાસ કરો\",\n    export_source: \"SQL નિકાસ કરો\",\n    models: \"મોડેલ્સ\",\n    exit: \"બહાર નીકળો\",\n    edit: \"સંપાદિત કરો\",\n    undo: \"અનડૂ\",\n    redo: \"રીડૂ\",\n    clear: \"સાફ કરો\",\n    are_you_sure_clear:\n      \"શું તમે ખરેખર આ ડાયાગ્રામ સાફ કરવા માંગો છો? આ અપરિવર્તનીય છે.\",\n    cut: \"કાપો\",\n    copy: \"કૉપિ કરો\",\n    paste: \"પેસ્ટ કરો\",\n    duplicate: \"ડુપ્લિકેટ\",\n    delete: \"કાઢી નાંખો\",\n    copy_as_image: \"ઈમેજ તરીકે કૉપિ કરો\",\n    view: \"દ્રશ્ય\",\n    header: \"મેનુબાર\",\n    sidebar: \"સાઇડબાર\",\n    issues: \"સમસ્યાઓ\",\n    presentation_mode: \"પ્રેઝન્ટેશન મોડ\",\n    strict_mode: \"સ્ટ્રિક્ટ મોડ\",\n    field_details: \"ફિલ્ડ વિગતો\",\n    reset_view: \"દ્રશ્ય રિસેટ કરો\",\n    show_grid: \"ગ્રિડ બતાવો\",\n    snap_to_grid: \"ગ્રિડ પર સ્નેપ કરો\",\n    show_datatype: \"ડેટાટાઇપ બતાવો\",\n    show_cardinality: \"કાર્ડિનાલિટી બતાવો\",\n    theme: \"થીમ\",\n    light: \"લાઇટ\",\n    dark: \"ડાર્ક\",\n    zoom_in: \"ઝૂમ ઇન\",\n    zoom_out: \"ઝૂમ આઉટ\",\n    fullscreen: \"પૂર્ણસ્ક્રીન\",\n    settings: \"સેટિંગ્સ\",\n    show_timeline: \"ટાઇમલાઇન બતાવો\",\n    autosave: \"ઓટોસેવ\",\n    panning: \"પેનિંગ\",\n    show_debug_coordinates: \"ડીબગ કોઓર્ડિનેટ્સ બતાવો\",\n    transform: \"ટ્રાન્સફોર્મ\",\n    viewbox: \"વ્યુ બોક્સ\",\n    cursor_coordinates: \"કર્સર કોઓર્ડિનેટ્સ\",\n    coordinate_space: \"જગ્યા\",\n    coordinate_space_screen: \"સ્ક્રીન\",\n    coordinate_space_diagram: \"ડાયાગ્રામ\",\n    table_width: \"ટેબલની પહોળાઈ\",\n    language: \"ભાષા\",\n    flush_storage: \"સ્ટોરેજ ફ્લશ કરો\",\n    are_you_sure_flush_storage:\n      \"શું તમે ખરેખર સ્ટોરેજ ફ્લશ કરવા માંગો છો? આ તમારા તમામ ડાયાગ્રામ અને કસ્ટમ ટેમ્પલેટ્સને કાયમ માટે કાઢી નાખશે.\",\n    storage_flushed: \"સ્ટોરેજ ફ્લશ કરાયું\",\n    help: \"મદદ\",\n    shortcuts: \"શોર્ટકટ્સ\",\n    ask_on_discord: \"અમને Discord પર પૂછો\",\n    feedback: \"પ્રતિસાદ\",\n    no_changes: \"કોઈ ફેરફારો નથી\",\n    loading: \"લોડ થઈ રહ્યું છે...\",\n    last_saved: \"છેલ્લે સેવ કરેલું\",\n    saving: \"સેવ થઈ રહ્યું છે...\",\n    failed_to_save: \"સેવ કરવામાં નિષ્ફળ\",\n    fit_window_reset: \"વિંડોમાં ફિટ કરો / રિસેટ કરો\",\n    zoom: \"ઝૂમ\",\n    add_table: \"ટેબલ ઉમેરો\",\n    add_area: \"વિસ્તાર ઉમેરો\",\n    add_note: \"નોંધ ઉમેરો\",\n    add_type: \"પ્રકાર ઉમેરો\",\n    to_do: \"કરવા માટે\",\n    tables: \"ટેબલો\",\n    relationships: \"સંબંધો\",\n    subject_areas: \"વિષય વિસ્તારો\",\n    notes: \"નોંધો\",\n    types: \"પ્રકારો\",\n    search: \"શોધો...\",\n    no_tables: \"કોઈ ટેબલો નથી\",\n    no_tables_text: \"તમારો ડાયાગ્રામ બનાવવાનું શરૂ કરો!\",\n    no_relationships: \"કોઈ સંબંધો નથી\",\n    no_relationships_text: \"ફિલ્ડ્સને જોડવા માટે ખેંચો અને સંબંધો બનાવો!\",\n    no_subject_areas: \"કોઈ વિષય વિસ્તારો નથી\",\n    no_subject_areas_text: \"ટેબલોને જૂથબદ્ધ કરવા માટે વિષય વિસ્તારો ઉમેરો!\",\n    no_notes: \"કોઈ નોંધો નથી\",\n    no_notes_text: \"વધારાની માહિતી નોંધવા માટે નોંધોનો ઉપયોગ કરો\",\n    no_types: \"કોઈ પ્રકારો નથી\",\n    no_types_text: \"તમારા પોતાના કસ્ટમ ડેટા પ્રકારો બનાવો\",\n    no_issues: \"કોઈ સમસ્યાઓ મળી નથી.\",\n    strict_mode_is_on_no_issues:\n      \"સ્ટ્રિક્ટ મોડ બંધ છે તેથી કોઈ સમસ્યાઓ બતાવવામાં આવશે નહીં.\",\n    name: \"નામ\",\n    type: \"પ્રકાર\",\n    null: \"નલ\",\n    not_null: \"નલ નથી\",\n    nullable: \"નલ હોઈ શકે\",\n    primary: \"પ્રાથમિક\",\n    unique: \"અનન્ય\",\n    autoincrement: \"સ્વયંવર્ધિત\",\n    default_value: \"ડિફૉલ્ટ\",\n    check: \"તપાસો અભિવ્યક્તિ\",\n    this_will_appear_as_is: \"*આ જનરેટ થયેલ સ્ક્રિપ્ટમાં જેમ છે તેમ દેખાશે.\",\n    comment: \"ટિપ્પણી\",\n    add_field: \"ફિલ્ડ ઉમેરો\",\n    values: \"મૂલ્યો\",\n    size: \"માપ\",\n    precision: \"ચોકસાઈ\",\n    set_precision: \"ચોકસાઈ સેટ કરો: 'માપ, અંકો'\",\n    use_for_batch_input: \"બેચ ઇનપુટ માટે , નો ઉપયોગ કરો\",\n    indices: \"ઇન્ડેક્સિસ\",\n    add_index: \"ઇન્ડેક્સ ઉમેરો\",\n    select_fields: \"ફિલ્ડ્સ પસંદ કરો\",\n    title: \"શીર્ષક\",\n    not_set: \"સેટ નથી\",\n    foreign: \"વિદેશી\",\n    cardinality: \"કાર્ડિનાલિટી\",\n    on_update: \"અપડેટ પર\",\n    on_delete: \"ડિલીટ પર\",\n    swap: \"સ્વેપ\",\n    one_to_one: \"એક થી એક\",\n    one_to_many: \"એક થી અનેક\",\n    many_to_one: \"અનેક થી એક\",\n    content: \"સામગ્રી\",\n    types_info:\n      \"આ સુવિધા object-relational DBMS જેમ કે PostgreSQL માટે છે.\\nજો MySQL અથવા MariaDB માટે ઉપયોગમાં લેવામાં આવે છે, તો સંબંધિત json માન્યતા ચકાસણી સાથે એક JSON પ્રકાર જનરેટ થશે.\\nજો SQLite માટે ઉપયોગમાં લેવામાં આવે છે તો તેને BLOBમાં રૂપાંતરિત કરવામાં આવશે.\\nજો MSSQL માટે ઉપયોગમાં લેવામાં આવે છે તો પહેલા ફિલ્ડ માટે એક પ્રકાર ઉપનામ જનરેટ થશે.\",\n    table_deleted: \"ટેબલ કાઢી નાખ્યું\",\n    area_deleted: \"વિસ્તાર કાઢી નાખ્યો\",\n    note_deleted: \"નોંધ કાઢી નાખી\",\n    relationship_deleted: \"સંબંધ કાઢી નાખ્યો\",\n    type_deleted: \"પ્રકાર કાઢી નાખ્યો\",\n    cannot_connect: \"કનેક્ટ કરી શકાતું નથી, કોલમના પ્રકારો અલગ છે\",\n    copied_to_clipboard: \"ક્લિપબોર્ડ પર કૉપિ કર્યું\",\n    create_new_diagram: \"નવો ડાયાગ્રામ બનાવો\",\n    cancel: \"રદ કરો\",\n    open_diagram: \"ડાયાગ્રામ ખોલો\",\n    rename_diagram: \"ડાયાગ્રામનું નામ બદલો\",\n    export: \"નિકાસ\",\n    export_image: \"ઈમેજ નિકાસ કરો\",\n    create: \"બનાવો\",\n    confirm: \"પુષ્ટિ કરો\",\n    last_modified: \"છેલ્લે સુધારેલ\",\n    drag_and_drop_files: \"ફાઇલોને અહીં ડ્રેગ અને ડ્રોપ કરો અથવા અપલોડ કરવા માટે ક્લિક કરો.\",\n    upload_sql_to_generate_diagrams:\n      \"તમારા ટેબલો અને કોલમો આપમેળે જનરેટ કરવા માટે SQL ફાઇલ અપલોડ કરો.\",\n    overwrite_existing_diagram: \"વર્તમાન ડાયાગ્રામને ઓવરરાઈટ કરો\",\n    only_mysql_supported:\n      \"*હાલમાં ફક્ત MySQL સ્ક્રિપ્ટ્સ લોડ કરવાનું સમર્થિત છે.\",\n    blank: \"ખાલી\",\n    filename: \"ફાઇલનું નામ\",\n    table_w_no_name: \"નામ વિનાનું ટેબલ ઘોષિત કર્યું\",\n    duplicate_table_by_name: \"'{{tableName}}' નામનું ડુપ્લિકેટ ટેબલ\",\n    empty_field_name: \"ટેબલ '{{tableName}}' માં ખાલી ફિલ્ડ `name`\",\n    empty_field_type: \"ટેબલ '{{tableName}}' માં ખાલી ફિલ્ડ `type`\",\n    no_values_for_field:\n      \"ટેબલ '{{tableName}}' ના ફિલ્ડ '{{fieldName}}' નો પ્રકાર `{{type}}` છે પરંતુ કોઈ મૂલ્ય નિર્દિષ્ટ નથી\",\n    default_doesnt_match_type:\n      \"ટેબલ '{{tableName}}' માં ફિલ્ડ '{{fieldName}}' નું ડિફોલ્ટ મૂલ્ય તેના પ્રકાર સાથે મેળ ખાતું નથી\",\n    not_null_is_null:\n      \"ટેબલ '{{tableName}}' ના ફિલ્ડ '{{fieldName}}' નું મૂલ્ય NOT NULL છે પરંતુ ડિફોલ્ટ NULL છે\",\n    duplicate_fields:\n      \"ટેબલ '{{tableName}}' માં નામ '{{fieldName}}' વાળા ડુપ્લિકેટ ટેબલ ફિલ્ડ્સ\",\n    duplicate_index:\n      \"ટેબલ '{{tableName}}' માં નામ '{{indexName}}' વાળો ડુપ્લિકેટ ઈન્ડેક્સ\",\n    empty_index: \"ટેબલ '{{tableName}}' માં ઈન્ડેક્સ કોઈ કૉલમ ઈન્ડેક્સ કરતું નથી\",\n    no_primary_key: \"ટેબલ '{{tableName}}' માં કોઈ પ્રાથમિક કી નથી\",\n    type_with_no_name: \"કોઈ નામ ન હોય તેવા પ્રકારને ઘોષિત કર્યું\",\n    duplicate_types: \"નામ '{{typeName}}' વાળા ડુપ્લિકેટ પ્રકારો\",\n    type_w_no_fields: \"કોઈ ફિલ્ડ્સ ન હોય તેવા પ્રકાર '{{typeName}}' ને ઘોષિત કર્યું\",\n    empty_type_field_name: \"પ્રકાર '{{typeName}}' માં ખાલી ફિલ્ડ `name`\",\n    empty_type_field_type: \"પ્રકાર '{{typeName}}' માં ખાલી ફિલ્ડ `type`\",\n    no_values_for_type_field:\n      \"પ્રકાર '{{typeName}}' ના ફિલ્ડ '{{fieldName}}' નો પ્રકાર `{{type}}` છે પરંતુ કોઈ મૂલ્ય નિર્દિષ્ટ નથી\",\n    duplicate_type_fields:\n      \"પ્રકાર '{{typeName}}' માં નામ '{{fieldName}}' વાળા ડુપ્લિકેટ પ્રકાર ફિલ્ડ્સ\",\n    duplicate_reference: \"નામ '{{refName}}' વાળો ડુપ્લિકેટ સંદર્ભ\",\n    circular_dependency: \"ટેબલ '{{refName}}' માં પરિપત્ર નિર્ભરતા\",\n    timeline: \"ટાઈમલાઈન\",\n    priority: \"પ્રાથમિકતા\",\n    none: \"કંઈ નહીં\",\n    low: \"ઓછી\",\n    medium: \"મધ્યમ\",\n    high: \"ઉચ્ચ\",\n    sort_by: \"આના દ્વારા સોર્ટ કરો\",\n    my_order: \"મારો ક્રમ\",\n    completed: \"પૂર્ણ\",\n    alphabetically: \"મૂળાક્ષરો પ્રમાણે\",\n    add_task: \"કાર્ય ઉમેરો\",\n    details: \"વિગતો\",\n    no_tasks: \"તમારી પાસે હજુ સુધી કોઈ કાર્યો નથી.\",\n    no_activity: \"તમારી પાસે હજુ સુધી કોઈ પ્રવૃત્તિ નથી.\",\n    move_element: \"{{name}} ને {{coords}} પર ખસેડો\",\n    edit_area: \"{{extra}} વિસ્તાર {{areaName}} સંપાદિત કરો\",\n    delete_area: \"વિસ્તાર {{areaName}} કાઢી નાખો\",\n    edit_note: \"{{extra}} નોંધ {{noteTitle}} સંપાદિત કરો\",\n    delete_note: \"નોંધ {{noteTitle}} કાઢી નાખો\",\n    edit_table: \"{{extra}} ટેબલ {{tableName}} સંપાદિત કરો\",\n    delete_table: \"ટેબલ {{tableName}} કાઢી નાખો\",\n    edit_type: \"{{extra}} પ્રકાર {{typeName}} સંપાદિત કરો\",\n    delete_type: \"પ્રકાર {{typeName}} કાઢી નાખો\",\n    add_relationship: \"સંબંધ ઉમેરો\",\n    edit_relationship: \"{{extra}} સંબંધ {{refName}} સંપાદિત કરો\",\n    delete_relationship: \"સંબંધ {{refName}} કાઢી નાખો\",\n    not_found: \"મળ્યું નથી\",\n    pick_db: \"ડેટાબેઝ પસંદ કરો\",\n    generic: \"સામાન્ય\",\n    generic_description:\n      \"સામાન્ય ડાયાગ્રામ્સ કોઈપણ SQL ફ્લેવરમાં નિકાસ કરી શકાય છે પરંતુ થોડા ડેટા પ્રકારોને સપોર્ટ કરે છે.\",\n    enums: \"ઇનમ્સ\",\n    add_enum: \"Enum ઉમેરો\",\n    edit_enum: \"{{extra}} Enum {{enumName}} સંપાદિત કરો\",\n    delete_enum: \"Enum કાઢી નાખો\",\n    enum_w_no_name: \"નામ વિના Enum મળ્યું\",\n    enum_w_no_values: \"મૂલ્યો વિના Enum '{{enumName}}' મળ્યું\",\n    duplicate_enums: \"નામ '{{enumName}}' સાથે ડુપ્લિકેટ Enums\",\n    enum_deleted: \"Enum કાઢી નાખ્યું\",\n    no_enums: \"કોઈ Enums નથી\",\n    no_enums_text: \"અહીં Enums વ્યાખ્યાયિત કરો\",\n    declare_array: \"એરે ઘોષિત કરો\",\n    empty_index_name: \"ટેબલ '{{tableName}}' માં નામ વિના ઇન્ડેક્સ ઘોષિત કર્યું\",\n    didnt_find_diagram: \"અરે! ડાયાગ્રામ મળ્યું નથી.\",\n    unsigned: \"સહી વગરનું\",\n    share: \"શેર કરો\",\n    unshare: \"અનશેર કરો\",\n    copy_link: \"લિંક કૉપિ કરો\",\n    readme: \"README\",\n    failed_to_load: \"લોડ કરવામાં નિષ્ફળ. ખાતરી કરો કે લિંક સાચી છે.\",\n    share_info:\n      \"* આ લિંક શેર કરવાથી લાઈવ રીયલ-ટાઇમ સહયોગ સત્ર બનશે નહીં.\",\n    show_relationship_labels: \"સંબંધ લેબલ્સ બતાવો\",\n    docs: \"દસ્તાવેજીકરણ\",\n    supported_types: \"સપોર્ટેડ ફાઇલ પ્રકારો:\",\n    bulk_update: \"જથ્થાબંધ અપડેટ\",\n    multiselect: \"મલ્ટીસિલેક્ટ\",\n    export_saved_data: \"સેવ કરેલ ડેટા નિકાસ કરો\",\n    dbml_view: \"DBML દૃશ્ય\",\n    tab_view: \"ટેબ દૃશ્ય\",\n    label: \"લેબલ\",\n    many_side_label: \"ઘણી(n) બાજુનું લેબલ\",\n    version: \"આવૃત્તિ\",\n    versions: \"આવૃત્તિઓ\",\n    no_saved_versions: \"કોઈ સેવ કરેલી આવૃત્તિઓ નથી\",\n    record_version: \"આવૃત્તિ રેકોર્ડ કરો\",\n    commited_at: \"પર કમિટ કર્યું\",\n    read_only: \"ફક્ત વાંચવા માટે\",\n    continue: \"ચાલુ રાખો\",\n    restore_version: \"આવૃત્તિ પુનઃસ્થાપિત કરો\",\n    restore_warning: \"બીજી આવૃત્તિ લોડ કરવાથી કોઈપણ ફેરફારો ઓવરરાઈટ થશે.\",\n    return_to_current: \"ડાયાગ્રામ પર પાછા ફરો\",\n    no_changes_to_record: \"રેકોર્ડ કરવા માટે કોઈ ફેરફાર નથી\",\n    click_to_view: \"જોવા માટે ક્લિક કરો\",\n    load_more: \"વધુ લોડ કરો\",\n    clear_cache: \"કેશ સાફ કરો\",\n    cache_cleared: \"કેશ સાફ થઈ ગઈ\",\n    failed_to_record_version: \"આવૃત્તિ રેકોર્ડ કરવામાં નિષ્ફળ\",\n    failed_to_load_diagram: \"ડાયાગ્રામ લોડ કરવામાં નિષ્ફળ\",\n    see_all: \"બધું જુઓ\",\n    insert_sql: \"SQL દાખલ કરો\",\n    upload_file: \"ફાઇલ અપલોડ કરો\",\n  },\n};\n\nexport { gu, gujarati };\n"
  },
  {
    "path": "src/i18n/locales/he.js",
    "content": "const hebrew = {\n  name: \"Hebrew\",\n  native_name: \"עברית\",\n  code: \"he\",\n};\n\nconst he = {\n  translation: {\n    report_bug: \"דווח על באג\",\n    import_from: \"ייבוא\",\n    import: \"ייבוא\",\n    file: \"קובץ\",\n    new: \"חדש\",\n    new_window: \"חלון חדש\",\n    open: \"פתח\",\n    save: \"שמור\",\n    save_as: \"שמור בשם\",\n    save_as_template: \"שמור כתבנית\",\n    template_saved: \"תבנית נשמרה!\",\n    rename: \"שנה שם\",\n    delete_diagram: \"מחק דיאגרמה\",\n    are_you_sure_delete_diagram:\n      \"האם אתה בטוח שברצונך למחוק דיאגרמה זו? פעולה זו אינה ניתנת לביטול.\",\n    oops_smth_went_wrong: \"אופס! משהו השתבש.\",\n    import_diagram: \"ייבא דיאגרמה\",\n    import_from_source: \"ייבוא מ-SQL\",\n    export_as: \"ייצוא כ\",\n    export_source: \"ייצא SQL\",\n    models: \"מודלים\",\n    exit: \"יציאה\",\n    edit: \"ערוך\",\n    undo: \"בטל\",\n    redo: \"בצע שוב\",\n    clear: \"נקה\",\n    are_you_sure_clear:\n      \"האם אתה בטוח שברצונך לנקות את הדיאגרמה? פעולה זו אינה ניתנת לביטול.\",\n    cut: \"גזור\",\n    copy: \"העתק\",\n    paste: \"הדבק\",\n    duplicate: \"שכפל\",\n    delete: \"מחק\",\n    copy_as_image: \"העתק כתמונה\",\n    view: \"הצג\",\n    header: \"תפריט עליון\",\n    sidebar: \"תפריט צדדי\",\n    issues: \"בעיות\",\n    presentation_mode: \"מצב מצגת\",\n    strict_mode: \"מצב קפדני\",\n    field_details: \"פרטי שדה\",\n    reset_view: \"אפס תצוגה\",\n    show_grid: \"הצג רשת\",\n    show_cardinality: \"הצג קרדינליות\",\n    theme: \"ערכת נושא\",\n    light: \"בהיר\",\n    dark: \"כהה\",\n    zoom_in: \"הגדל\",\n    zoom_out: \"הקטן\",\n    fullscreen: \"מסך מלא\",\n    settings: \"הגדרות\",\n    show_timeline: \"הצג ציר זמן\",\n    autosave: \"שמירה אוטומטית\",\n    panning: \"הזזה\",\n    show_debug_coordinates: \"הצג קואורדינטות ניפוי באגים\",\n    transform: \"המר\",\n    viewbox: \"תיבת תצוגה\",\n    cursor_coordinates: \"קואורדינטות סמן\",\n    coordinate_space: \"מרחב\",\n    coordinate_space_screen: \"מסך\",\n    coordinate_space_diagram: \"דיאגרמה\",\n    table_width: \"רוחב טבלה\",\n    language: \"שפה\",\n    flush_storage: \"נקה אחסון\",\n    are_you_sure_flush_storage:\n      \"האם אתה בטוח שברצונך לנקות את האחסון? פעולה זו תמחק באופן בלתי הפיך את כל הדיאגרמות והתבניות המותאמות אישית שלך.\",\n    storage_flushed: \"אחסון נוקה\",\n    help: \"עזרה\",\n    shortcuts: \"קיצורי דרך\",\n    ask_on_discord: \"שאל אותנו ב-Discord\",\n    feedback: \"משוב\",\n    no_changes: \"אין שינויים\",\n    loading: \"טוען...\",\n    last_saved: \"נשמר לאחרונה\",\n    saving: \"שומר...\",\n    failed_to_save: \"שמירה נכשלה\",\n    fit_window_reset: \"התאם חלון / איפוס\",\n    zoom: \"זום\",\n    add_table: \"הוסף טבלה\",\n    add_area: \"הוסף אזור\",\n    add_note: \"הוסף הערה\",\n    add_type: \"הוסף סוג\",\n    to_do: \"לביצוע\",\n    tables: \"טבלאות\",\n    relationships: \"קשרים\",\n    subject_areas: \"תחומי עניין\",\n    notes: \"הערות\",\n    types: \"סוגים\",\n    search: \"חיפוש...\",\n    no_tables: \"אין טבלאות\",\n    no_tables_text: \"התחל לבנות את הדיאגרמה שלך!\",\n    no_relationships: \"אין קשרים\",\n    no_relationships_text: \"גרור כדי לחבר שדות וליצור קשרים!\",\n    no_subject_areas: \"אין תחומי עניין\",\n    no_subject_areas_text: \"הוסף תחומי עניין כדי לקבץ טבלאות!\",\n    no_notes: \"אין הערות\",\n    no_notes_text: \"השתמש בהערות כדי לרשום מידע נוסף\",\n    no_types: \"אין סוגים\",\n    no_types_text: \"צור סוגי נתונים מותאמים אישית\",\n    no_issues: \"לא נמצאו בעיות.\",\n    strict_mode_is_on_no_issues: \"מצב קפדני כבוי ולכן לא יוצגו בעיות.\",\n    name: \"שם\",\n    type: \"סוג\",\n    null: \"ריק\",\n    not_null: \"לא ריק\",\n    primary: \"ראשי\",\n    unique: \"ייחודי\",\n    autoincrement: \"הגדלה אוטומטית\",\n    default_value: \"ברירת מחדל\",\n    check: \"ביטוי בדיקה\",\n    this_will_appear_as_is: \"*זה יופיע בסקריפט שנוצר כמו שהוא.\",\n    comment: \"הערה\",\n    add_field: \"הוסף שדה\",\n    values: \"ערכים\",\n    size: \"גודל\",\n    precision: \"דיוק\",\n    set_precision: \"הגדר דיוק: (גודל, ספרות)\",\n    use_for_batch_input: \"השתמש ב-, להזנת קבוצות\",\n    indices: \"אינדקסים\",\n    add_index: \"הוסף אינדקס\",\n    select_fields: \"בחר שדות\",\n    title: \"כותרת\",\n    not_set: \"לא מוגדר\",\n    foreign: \"זר\",\n    cardinality: \"קרדינליות\",\n    on_update: \"בזמן עדכון\",\n    on_delete: \"בזמן מחיקה\",\n    swap: \"החלף\",\n    one_to_one: \"אחד לאחד\",\n    one_to_many: \"אחד לרבים\",\n    many_to_one: \"רבים לאחד\",\n    content: \"תוכן\",\n    types_info:\n      \"תכונה זו מיועדת למערכות ניהול נתונים אובייקט-רלציוניות כמו PostgreSQL.\\nאם משמשת עבור MySQL או MariaDB תיווצר סוג JSON עם בדיקת תוקף json תואמת.\\nאם משמשת עבור SQLite היא תתורגם ל-BLOB.\\nאם משמשת עבור MSSQL תיווצר סוג סינונימי לשדה הראשון.\",\n    table_deleted: \"טבלה נמחקה\",\n    area_deleted: \"אזור נמחק\",\n    note_deleted: \"הערה נמחקה\",\n    relationship_deleted: \"קשר נמחק\",\n    type_deleted: \"סוג נמחק\",\n    cannot_connect: \"לא ניתן לחבר, העמודות הן מסוגים שונים\",\n    copied_to_clipboard: \"הועתק ללוח\",\n    create_new_diagram: \"צור דיאגרמה חדשה\",\n    cancel: \"בטל\",\n    open_diagram: \"פתח דיאגרמה\",\n    rename_diagram: \"שנה שם לדיאגרמה\",\n    export: \"ייצוא\",\n    export_image: \"ייצא תמונה\",\n    create: \"צור\",\n    confirm: \"אשר\",\n    last_modified: \"נערך לאחרונה\",\n    drag_and_drop_files: \"גרור ושחרר את הקובץ כאן או לחץ להעלאה.\",\n    upload_sql_to_generate_diagrams:\n      \"העלה קובץ SQL כדי ליצור באופן אוטומטי את הטבלאות והעמודות שלך.\",\n    overwrite_existing_diagram: \"דרוס דיאגרמה קיימת\",\n    only_mysql_supported: \"*כרגע נתמך רק טעינת סקריפטים של MySQL.\",\n    blank: \"ריק\",\n    filename: \"שם קובץ\",\n    table_w_no_name: \"הוכרז טבלה ללא שם\",\n    duplicate_table_by_name: \"שכפול טבלה בשם '{{tableName}}'\",\n    empty_field_name: \"שדה `name` ריק בטבלה '{{tableName}}'\",\n    empty_field_type: \"שדה `type` ריק בטבלה '{{tableName}}'\",\n    no_values_for_field:\n      \"שדה '{{fieldName}}' בטבלה '{{tableName}}' הוא מסוג `{{type}}` אך לא הוגדרו ערכים\",\n    default_doesnt_match_type:\n      \"ערך ברירת מחדל עבור שדה '{{fieldName}}' בטבלה '{{tableName}}' אינו תואם לסוג שלו\",\n    not_null_is_null:\n      \"שדה '{{fieldName}}' בטבלה '{{tableName}}' אינו ריק אך ערך ברירת מחדל הוא NULL\",\n    duplicate_fields:\n      \"שדות טבלה כפולים בשם '{{fieldName}}' בטבלה '{{tableName}}'\",\n    duplicate_index: \"אינדקס כפול בשם '{{indexName}}' בטבלה '{{tableName}}'\",\n    empty_index: \"אינדקס בטבלה '{{tableName}}' אינו מאנדקס שום עמודות\",\n    no_primary_key: \"לטבלה '{{tableName}}' אין מפתח ראשי\",\n    type_with_no_name: \"הוכרז סוג ללא שם\",\n    duplicate_types: \"סוגים כפולים בשם '{{typeName}}'\",\n    type_w_no_fields: \"הוכרז סוג ריק '{{typeName}}' ללא שדות\",\n    empty_type_field_name: \"שדה `name` ריק בסוג '{{typeName}}'\",\n    empty_type_field_type: \"שדה `type` ריק בסוג '{{typeName}}'\",\n    no_values_for_type_field:\n      \"שדה '{{fieldName}}' בסוג '{{typeName}}' הוא מסוג `{{type}}` אך לא הוגדרו ערכים\",\n    duplicate_type_fields:\n      \"שדות סוג כפולים בשם '{{fieldName}}' בסוג '{{typeName}}'\",\n    duplicate_reference: \"הפניה כפולה בשם '{{refName}}'\",\n    circular_dependency: \"תלות מעגלית בטבלה '{{refName}}'\",\n    timeline: \"ציר זמן\",\n    priority: \"עדיפות\",\n    none: \"ללא\",\n    low: \"נמוכה\",\n    medium: \"בינונית\",\n    high: \"גבוהה\",\n    sort_by: \"מיין לפי\",\n    my_order: \"הסדר שלי\",\n    completed: \"הושלם\",\n    alphabetically: \"בסדר אלפביתי\",\n    add_task: \"הוסף משימה\",\n    details: \"פרטים\",\n    no_tasks: \"אין לך משימות עדיין.\",\n    no_activity: \"אין לך פעילות עדיין.\",\n    move_element: \"העבר {{name}} ל{{coords}}\",\n    edit_area: \"{{extra}} ערוך אזור {{areaName}}\",\n    delete_area: \"מחק אזור {{areaName}}\",\n    edit_note: \"{{extra}} ערוך הערה {{noteTitle}}\",\n    delete_note: \"מחק הערה {{noteTitle}}\",\n    edit_table: \"{{extra}} ערוך טבלה {{tableName}}\",\n    delete_table: \"מחק טבלה {{tableName}}\",\n    edit_type: \"{{extra}} ערוך סוג {{typeName}}\",\n    delete_type: \"מחק סוג {{typeName}}\",\n    add_relationship: \"הוסף קשר\",\n    edit_relationship: \"{{extra}} ערוך קשר {{refName}}\",\n    delete_relationship: \"מחק קשר {{refName}}\",\n    not_found: \"לא נמצא\",\n    pick_db: \"בחר מסד נתונים\",\n    generic: \"כללי\",\n    generic_description:\n      \"דיאגרמות כלליות יכולות להיות מיוצאות לכל SQL אך תומכות בסוגי נתונים מועטים.\",\n    enums: \"מנויים\",\n    add_enum: \"הוסף מנוי\",\n    edit_enum: \"{{extra}} ערוך מנוי {{enumName}}\",\n    delete_enum: \"מחק מנוי\",\n    enum_w_no_name: \"נמצא מנוי ללא שם\",\n    enum_w_no_values: \"נמצא מנוי '{{enumName}}' ללא ערכים\",\n    duplicate_enums: \"מנויים כפולים בשם '{{enumName}}'\",\n    no_enums: \"אין מנויים\",\n    no_enums_text: \"הגדר מנויים כאן\",\n    declare_array: \"הכרז מערך\",\n    empty_index_name: \"הוכרז אינדקס ללא שם בטבלה '{{tableName}}'\",\n    didnt_find_diagram: \"אופס! לא נמצאה הדיאגרמה.\",\n  },\n};\n\nexport { he, hebrew };\n"
  },
  {
    "path": "src/i18n/locales/hi.js",
    "content": "const hindi = {\n  name: \"Hindi\",\n  native_name: \"हिंदी\",\n  code: \"hi\",\n};\n\nconst hi = {\n  translation: {\n    report_bug: \"बग रिपोर्ट करें\",\n    import_from: \"इम्पोर्ट\",\n    import: \"इम्पोर्ट\",\n    file: \"फ़ाइल\",\n    new: \"नया\",\n    new_window: \"नई विंडो\",\n    open: \"खोलें\",\n    open_recent: \"हाल में खोले गए\",\n    save: \"सेव\",\n    save_as: \"के रूप में सेव करें\",\n    save_as_template: \"टेम्पलेट के रूप में सेव करें\",\n    template_saved: \"टेम्पलेट सेव हो गया!\",\n    rename: \"नाम बदलें\",\n    delete_diagram: \"डायग्राम हटाएं\",\n    are_you_sure_delete_diagram:\n      \"क्या आप वाकई इस डायग्राम को हटाना चाहते हैं? यह क्रिया अपरिवर्तनीय है।\",\n    oops_smth_went_wrong: \"उफ़! कुछ गलत हो गया।\",\n    import_diagram: \"डायग्राम इम्पोर्ट करें\",\n    import_from_source: \"SQL से इम्पोर्ट करें\",\n    export_as: \"के रूप में एक्सपोर्ट करें\",\n    export_source: \"SQL एक्सपोर्ट करें\",\n    models: \"मॉडल्स\",\n    exit: \"बाहर निकलें\",\n    edit: \"एडिट करें\",\n    undo: \"पूर्ववत करें\",\n    redo: \"फिर से करें\",\n    clear: \"साफ़ करें\",\n    are_you_sure_clear:\n      \"क्या आप वाकई इस डायग्राम को साफ़ करना चाहते हैं? यह अपरिवर्तनीय है।\",\n    cut: \"काटें\",\n    copy: \"कॉपी करें\",\n    paste: \"पेस्ट करें\",\n    duplicate: \"प्रतिलिपि बनाएं\",\n    delete: \"हटाएं\",\n    copy_as_image: \"इमेज के रूप में कॉपी करें\",\n    view: \"दृश्य\",\n    header: \"मेनूबार\",\n    sidebar: \"साइडबार\",\n    issues: \"समस्याएं\",\n    presentation_mode: \"प्रस्तुति मोड\",\n    strict_mode: \"स्ट्रिक्ट मोड\",\n    field_details: \"फ़ील्ड डिटेल्स\",\n    reset_view: \"दृश्य रीसेट करें\",\n    show_grid: \"ग्रिड दिखाएं\",\n    show_cardinality: \"कार्डिनैलिटी दिखाएं\",\n    theme: \"थीम\",\n    light: \"प्रकाश\",\n    dark: \"अंधकार\",\n    zoom_in: \"ज़ूम इन\",\n    zoom_out: \"ज़ूम आउट\",\n    fullscreen: \"पूर्ण स्क्रीन\",\n    settings: \"सेटिंग्स\",\n    show_timeline: \"टाइमलाइन दिखाएं\",\n    autosave: \"ऑटोसेव\",\n    panning: \"पैनिंग\",\n    table_width: \"टेबल की चौड़ाई\",\n    language: \"भाषा\",\n    flush_storage: \"स्टोरेज साफ़ करें\",\n    are_you_sure_flush_storage:\n      \"क्या आप वाकई स्टोरेज को साफ़ करना चाहते हैं? यह सभी आपके डायग्राम और कस्टम टेम्पलेट्स को अपरिवर्तनीय रूप से हटा देगा।\",\n    storage_flushed: \"स्टोरेज साफ़ किया गया\",\n    help: \"मदद\",\n    shortcuts: \"शॉर्टकट्स\",\n    ask_on_discord: \"हमसे Discord पर पूछें\",\n    feedback: \"फीडबॅक\",\n    no_changes: \"कोई बदलाव नहीं\",\n    loading: \"लोड हो रहा है...\",\n    last_saved: \"आखिरी बार सेव्हड\",\n    saving: \"सेव हो रहा है...\",\n    failed_to_save: \"सेव करने में विफल\",\n    fit_window_reset: \"विंडो फिट करें / रीसेट करें\",\n    zoom: \"ज़ूम\",\n    add_table: \"टेबल जोड़ें\",\n    add_area: \"एरिया जोड़ें\",\n    add_note: \"नोट जोड़ें\",\n    add_type: \"प्रकार जोड़ें\",\n    to_do: \"करने के लिए\",\n    tables: \"टेबल्स\",\n    relationships: \"संबंध\",\n    subject_areas: \"सब्जेक्ट एरियाज\",\n    notes: \"नोट्स\",\n    types: \"प्रकार\",\n    search: \"खोजें...\",\n    no_tables: \"कोई टेबल्स नहीं\",\n    no_tables_text: \"अपना डायग्राम बनाना शुरू करें!\",\n    no_relationships: \"कोई संबंध नहीं\",\n    no_relationships_text:\n      \"फील्ड्स को कनेक्ट करने के लिए खींचें और संबंध बनाएं!\",\n    no_subject_areas: \"कोई विषय एरियाज नहीं\",\n    no_subject_areas_text: \"ग्रूप टेबल्स को सब्जेक्ट एरियाज जोड़ें!\",\n    no_notes: \"कोई नोट्स नहीं\",\n    no_notes_text: \"अतिरिक्त जानकारी रिकॉर्ड करने के लिए नोट्स का उपयोग करें\",\n    no_types: \"कोई प्रकार नहीं\",\n    no_types_text: \"अपने स्वयं के कस्टम डेटा प्रकार बनाएं\",\n    no_issues: \"कोई समस्याएं नहीं पाए गए।\",\n    strict_mode_is_on_no_issues:\n      \"स्ट्रिक्ट मोड बंद है इसलिए कोई समस्याएं नहीं दिखाए जाएंगे।\",\n    name: \"नाम\",\n    type: \"प्रकार\",\n    null: \"व्यर्थ\",\n    not_null: \"नॉट व्यर्थ\",\n    primary: \"प्राथमिक\",\n    unique: \"युनिक\",\n    autoincrement: \"स्वतः वाढ\",\n    default_value: \"डिफ़ॉल्ट\",\n    check: \"चेक एक्सप्रेशन\",\n    this_will_appear_as_is:\n      \"*यह जेनरेटेड स्क्रिप्ट में जैसा है वैसा ही दिखेगा।\",\n    comment: \"टिप्पणी\",\n    add_field: \"फ़ील्ड जोड़ें\",\n    values: \"व्हॅल्यूज\",\n    size: \"साइज\",\n    precision: \"सटीकता\",\n    set_precision: \"सटीकता सेट करें: (साइज, डिजिट्स)\",\n    use_for_batch_input: \"उपयोग करें, बैच इनपुट के लिए\",\n    indices: \"इंडायसेस\",\n    add_index: \"इंडेक्स जोड़ें\",\n    select_fields: \"फ़ील्ड्स चुनें\",\n    title: \"शीर्षक\",\n    not_set: \"सेट नहीं किया गया\",\n    foreign: \"फॉरेन\",\n    cardinality: \"कार्डिनैलिटी\",\n    on_update: \"अपडेट पर\",\n    on_delete: \"हटाने पर\",\n    swap: \"स्वैप\",\n    one_to_one: \"एक से एक\",\n    one_to_many: \"एक से कई\",\n    many_to_one: \"कई से एक\",\n    content: \"कंटेंट\",\n    types_info:\n      \"यह सुविधा object-relational DBMS जैसे PostgreSQL के लिए है।\\nयदि MySQL या MariaDB के लिए उपयोग किया जाता है, तो एक JSON प्रकार जेनरेट किया जाएगा जिसमें संबंधित json वैधता जांच होगी।\\nयदि SQLite के लिए उपयोग किया जाता है तो इसे BLOB में परिवर्तित किया जाएगा।\\nयदि MSSQL के लिए उपयोग किया जाता है तो पहले फ़ील्ड के लिए एक प्रकार उपनाम जेनरेट किया जाएगा।\",\n    table_deleted: \"टेबल हटाई गई\",\n    area_deleted: \"एरिया हटाया गया\",\n    note_deleted: \"नोट हटाया गया\",\n    relationship_deleted: \"संबंध हटाया गया\",\n    type_deleted: \"प्रकार हटाया गया\",\n    cannot_connect: \"कनेक्ट नहीं कर सकते, कॉलम के प्रकार अलग-अलग हैं\",\n    copied_to_clipboard: \"क्लिपबोर्ड पर कॉपी किया गया\",\n    create_new_diagram: \"नया डायग्राम बनाएं\",\n    cancel: \"रद्द करें\",\n    open_diagram: \"डायग्राम खोलें\",\n    rename_diagram: \"डायग्राम का नाम बदलें\",\n    export: \"एक्सपोर्ट\",\n    export_image: \"एक्सपोर्ट इमेज\",\n    create: \"बनाएं\",\n    confirm: \"पुष्टि करें\",\n    last_modified: \"अंतिम बार मॉडिफाइड\",\n    drag_and_drop_files:\n      \"फ़ाइल को यहां खींचें और छोड़ें या अपलोड करने के लिए क्लिक करें।\",\n    upload_sql_to_generate_diagrams:\n      \"अपनी टेबल और कॉलम को स्वचालित रूप से जेनरेट करने के लिए एक sql फ़ाइल अपलोड करें।\",\n    overwrite_existing_diagram: \"मौजूदा डायग्राम को अधिलेखित करें\",\n    only_mysql_supported:\n      \"*फिलहाल केवल MySQL स्क्रिप्ट्स को लोड करना समर्थित है।\",\n    blank: \"खाली\",\n    filename: \"फ़ाइलनाम\",\n    table_w_no_name: \"नाम के बिना टेबल घोषित की गई\",\n    duplicate_table_by_name: \"नाम से डुप्लिकेट टेबल '{{tableName}}'\",\n    empty_field_name: \"टेबल '{{tableName}}' में खाली फ़ील्ड `नाम`\",\n    empty_field_type: \"टेबल '{{tableName}}' में खाली फ़ील्ड `प्रकार`\",\n    no_values_for_field:\n      \"टेबल '{{tableName}}' के फ़ील्ड '{{fieldName}}' का प्रकार `{{type}}` है लेकिन कोई व्हॅल्यू निर्दिष्ट नहीं की गयी है\",\n    default_doesnt_match_type:\n      \"टेबल '{{tableName}}' में फ़ील्ड '{{fieldName}}' की डिफ़ॉल्ट व्हॅल्यू उसके प्रकार से मेल नहीं खाती\",\n    not_null_is_null:\n      \"टेबल '{{tableName}}' के फ़ील्ड '{{fieldName}}' की व्हॅल्यू NOT NULL है लेकिन डिफ़ॉल्ट NULL है\",\n    duplicate_fields:\n      \"टेबल '{{tableName}}' में नाम '{{fieldName}}' वाले डुप्लिकेट टेबल फ़ील्ड्स\",\n    duplicate_index:\n      \"टेबल '{{tableName}}' में नाम '{{indexName}}' वाला डुप्लिकेट इंडेक्स\",\n    empty_index: \"टेबल '{{tableName}}' में इंडेक्स कोई कॉलम इंडेक्स नहीं करता\",\n    no_primary_key: \"टेबल '{{tableName}}' में कोई प्राथमिक कुंजी नहीं है\",\n    type_with_no_name: \"कोई नाम नहीं होने वाले प्रकार को घोषित किया\",\n    duplicate_types: \"नाम '{{typeName}}' वाले डुप्लिकेट प्रकार\",\n    type_w_no_fields:\n      \"कोई फ़ील्ड्स नहीं होने वाले प्रकार '{{typeName}}' को घोषित किया\",\n    empty_type_field_name: \"प्रकार '{{typeName}}' में खाली फ़ील्ड `नाम`\",\n    empty_type_field_type: \"प्रकार '{{typeName}}' में खाली फ़ील्ड `प्रकार`\",\n    no_values_for_type_field:\n      \"प्रकार '{{typeName}}' के फ़ील्ड '{{fieldName}}' का प्रकार `{{type}}` है लेकिन कोई व्हॅल्यू निर्दिष्ट नहीं की गयी है\",\n    duplicate_type_fields:\n      \"प्रकार '{{typeName}}' में नाम '{{fieldName}}' वाले डुप्लिकेट प्रकार फ़ील्ड्स\",\n    duplicate_reference: \"नाम '{{refName}}' वाला डुप्लिकेट संदर्भ\",\n    circular_dependency: \"टेबल '{{refName}}' में परिपत्र निर्भरता\",\n    timeline: \"समयरेखा\",\n    priority: \"प्राथमिकता\",\n    none: \"कोई नहीं\",\n    low: \"निम्न\",\n    medium: \"मध्यम\",\n    high: \"उच्च\",\n    sort_by: \"द्वारा क्रमबद्ध करें\",\n    my_order: \"मेरा क्रम\",\n    completed: \"पूर्ण\",\n    alphabetically: \"वर्णानुक्रम में\",\n    add_task: \"कार्य जोड़ें\",\n    details: \"डिटेल्स\",\n    no_tasks: \"आपके पास अभी तक कोई कार्य नहीं है।\",\n    no_activity: \"आपके पास अभी तक कोई गतिविधि नहीं है।\",\n    move_element: \"{{name}} को {{coords}} पर ले जाएँ\",\n    edit_area: \"{{extra}} एडिट एरिया {{areaName}}\",\n    delete_area: \"एरिया हटाएं {{areaName}}\",\n    edit_note: \"{{extra}} नोट एडिट करें {{noteTitle}}\",\n    delete_note: \"नोट हटाएं {{noteTitle}}\",\n    edit_table: \"{{extra}} टेबल एडिट करें {{tableName}}\",\n    delete_table: \"टेबल हटाएं {{tableName}}\",\n    edit_type: \"{{extra}} प्रकार एडिट करें {{typeName}}\",\n    delete_type: \"प्रकार हटाएं {{typeName}}\",\n    add_relationship: \"संबंध जोड़ें\",\n    edit_relationship: \"{{extra}} संबंध एडिट करें {{refName}}\",\n    delete_relationship: \"संबंध हटाएं {{refName}}\",\n    not_found: \"नहीं मिला\",\n    no_saved_diagrams: \"आपके पास कोई सेव किया गया डायग्राम नहीं है\",\n    see_all: \"सभी देखें\",\n    versions: \"संस्करण\",\n    didnt_find_diagram: \"उफ़! डायग्राम नहीं मिला।\",\n  },\n};\n\nexport { hi, hindi };\n"
  },
  {
    "path": "src/i18n/locales/hu.js",
    "content": "const hungarian = {\n  name: \"Hungarian\",\n  native_name: \"Magyar\",\n  code: \"hu\",\n};\n\nconst hu = {\n  translation: {\n    report_bug: \"Hiba jelentése\",\n    import: \"Importálás\",\n    inherits: \"Öröklődések\",\n    merging_column_w_inherited_definition:\n      \"A(z) '{{tableName}}' tábla (örökölt definícióval) '{{fieldName}}' oszlopa összefűzésre fog kerülni\",\n    import_from: \"Importálás innen\",\n    file: \"Fájl\",\n    new: \"Új\",\n    new_window: \"Új ablak\",\n    no_saved_diagrams: \"Nincs mentett diagram\",\n    open: \"Megnyitás\",\n    open_recent: \"Legutóbbiak\",\n    save: \"Mentés\",\n    save_as: \"Mentés másként\",\n    save_as_template: \"Mentés sablonként\",\n    template_saved: \"Sablon elmentve!\",\n    rename: \"Átnevezés\",\n    delete_diagram: \"Diagram törlése\",\n    are_you_sure_delete_diagram:\n      \"Biztosan törli ezt a diagramot? Ez a művelet végleges.\",\n    oops_smth_went_wrong: \"Hoppá! Valami hiba történt.\",\n    import_diagram: \"Diagram importálása\",\n    import_from_source: \"Importálás SQL-ből\",\n    export_as: \"Exportálás mint\",\n    export_source: \"Exportálás SQL-be\",\n    models: \"Modellek\",\n    exit: \"Kilépés\",\n    edit: \"Szerkesztés\",\n    undo: \"Visszavonás\",\n    redo: \"Ismétlés\",\n    clear: \"Kitörlés\",\n    are_you_sure_clear:\n      \"Biztosan törli a diagram tartalmát? Ez a művelet végleges.\",\n    cut: \"Kivágás\",\n    copy: \"Másolás\",\n    paste: \"Beillesztés\",\n    duplicate: \"Duplikálás\",\n    delete: \"Törlés\",\n    copy_as_image: \"Másolás képként\",\n    view: \"Nézet\",\n    header: \"Menüsáv\",\n    sidebar: \"Oldalsáv\",\n    issues: \"Problémák\",\n    presentation_mode: \"Prezentációs mód\",\n    strict_mode: \"Szigorú mód\",\n    field_details: \"Mezők részletei\",\n    reset_view: \"Nézet alaphelyzetbe\",\n    show_grid: \"Rács\",\n    snap_to_grid: \"Rácshoz igazítás\",\n    show_datatype: \"Adattípus\",\n    show_cardinality: \"Kardinalitás\",\n    theme: \"Téma\",\n    light: \"Világos\",\n    dark: \"Sötét\",\n    zoom_in: \"Nagyítás\",\n    zoom_out: \"Kicsinyítés\",\n    fullscreen: \"Teljes képernyő\",\n    settings: \"Beállítások\",\n    show_timeline: \"Szerkesztési előzmények\",\n    autosave: \"Automatikus mentés\",\n    panning: \"Mozgatás\",\n    show_debug_coordinates: \"Hibakeresési koordináták\",\n    transform: \"Elhelyezkedés\",\n    viewbox: \"Szerkesztő\",\n    cursor_coordinates: \"Kurzor koordinátái\",\n    coordinate_space: \"Tér\",\n    coordinate_space_screen: \"Szerkesztő\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Táblák szélessége\",\n    language: \"Nyelv\",\n    flush_storage: \"Tárhely ürítése\",\n    are_you_sure_flush_storage:\n      \"Biztosan üríti a tárhelyet? Ez véglegesen törölni fogja minden diagramját és egyedi sablonját.\",\n    storage_flushed: \"A tárhely kiürítve\",\n    help: \"Súgó\",\n    shortcuts: \"Gyorsbillentyűk\",\n    ask_on_discord: \"Érdeklődjön Discord-on\",\n    feedback: \"Visszajelzés\",\n    no_changes: \"Nem volt módosítva\",\n    loading: \"Betöltés...\",\n    last_saved: \"Utoljára mentve:\",\n    saving: \"Mentés...\",\n    failed_to_save: \"A mentés sikertelen\",\n    fit_window_reset: \"Ablakhoz illesztés\",\n    zoom: \"Nagyítás\",\n    add_table: \"Új tábla\",\n    add_area: \"Új terület\",\n    add_note: \"Új jegyzet\",\n    add_type: \"Új típus\",\n    to_do: \"Teendők\",\n    tables: \"Táblák\",\n    relationships: \"Kapcsolatok\",\n    subject_areas: \"Területek\",\n    notes: \"Jegyzetek\",\n    types: \"Típusok\",\n    search: \"Keresés...\",\n    no_tables: \"Nincs tábla\",\n    no_tables_text: \"Vágjon bele diagramja elkészítésébe!\",\n    no_relationships: \"Nincs kapcsolat létrehozva\",\n    no_relationships_text:\n      \"Egérhúzással összeköthet mezőket kapcsolatok létrehozásához\",\n    no_subject_areas: \"Nincs terület hozzáadva\",\n    no_subject_areas_text:\n      \"Adjon hozzá területeket a táblák csoportosításához!\",\n    no_notes: \"Nincs jegyzet\",\n    no_notes_text: \"Használjon jegyzeteket további információk feljegyzéséhez\",\n    no_types: \"Nincs típus\",\n    no_types_text: \"Készítsen egyedi adattípusokat\",\n    no_issues: \"Nem észleltünk problémát.\",\n    strict_mode_is_on_no_issues:\n      \"A szigorú mód le van tiltva, így a problémák nem fognak megjelenni.\",\n    name: \"Név\",\n    type: \"Típus\",\n    null: \"Null\",\n    not_null: \"Nem null\",\n    nullable: \"Nullázható\",\n    primary: \"Elsődleges\",\n    unique: \"Egyedi\",\n    autoincrement: \"Automatikus növelés\",\n    default_value: \"Alapért.\",\n    check: \"'Check' kifejezés\",\n    this_will_appear_as_is:\n      \"*Ez a generált parancsfájlban ugyanígy fog megjelenni.\",\n    comment: \"Megjegyzés\",\n    add_field: \"Új mező\",\n    values: \"Értékek\",\n    size: \"Méret\",\n    precision: \"Pontosság\",\n    set_precision: \"Pontosság: 'méret, számjegyek'\",\n    use_for_batch_input: \"Több értéket vesszővel elválasztva adhat meg\",\n    indices: \"Indexek\",\n    add_index: \"Új index\",\n    select_fields: \"Mezők kiválasztása\",\n    title: \"Cím\",\n    not_set: \"Nincs megadva\",\n    foreign: \"Idegen\",\n    cardinality: \"Kardinalitás\",\n    on_update: \"Frissítéskor\",\n    on_delete: \"Törléskor\",\n    swap: \"Felcserélés\",\n    one_to_one: \"Egy-az-egyhez\",\n    one_to_many: \"Egy-a-többhöz\",\n    many_to_one: \"Több-az-egyhez\",\n    content: \"Tartalom\",\n    types_info:\n      \"Ez a funkció objektum-relációs adatbázisokhoz van tervezve, mint például a PostgreSQL.\\nHa MySQL-hez vagy MariaDB-hez van használva, egy JSON típus lesz generálva a megfelelő json validációval.\\nSQLite esetén BLOB típusként fog megjelenni.\\nMSSQL esetén pedig egy alternatív típusnév lesz generálva az első mezőhöz.\",\n    table_deleted: \"A tábla törölve\",\n    area_deleted: \"A terület törölve\",\n    note_deleted: \"A jegyzet törölve\",\n    relationship_deleted: \"A kapcsolat törölve\",\n    type_deleted: \"A típus törölve\",\n    cannot_connect:\n      \"A kapcsolatot nem lehet létrehozni, az oszlopok eltérő típusúak\",\n    copied_to_clipboard: \"Másolva a vágólapra\",\n    create_new_diagram: \"Új diagram létrehozása\",\n    cancel: \"Mégse\",\n    open_diagram: \"Diagram megnyitása\",\n    rename_diagram: \"Diagram átnevezése\",\n    export: \"Exportálás\",\n    export_image: \"Kép exportálása\",\n    create: \"Létrehozás\",\n    confirm: \"Megerősítés\",\n    last_modified: \"Utoljára módosítva\",\n    drag_and_drop_files:\n      \"Húzzon ide egy fájlt vagy kattintson a feltöltendő fájl kiválasztásához.\",\n    upload_sql_to_generate_diagrams:\n      \"Töltsön fel egy sql fájlt a táblák és oszlopok automatikus generálásához.\",\n    overwrite_existing_diagram: \"Meglévő diagram felülírása\",\n    only_mysql_supported: \"*Jelenleg csak MySQL fájlok betöltése támogatott.\",\n    blank: \"Üres\",\n    filename: \"Fájlnév\",\n    table_w_no_name: \"Nincs megadva név egy táblának\",\n    duplicate_table_by_name:\n      \"Több tábla is létezik ezzel a névvel: '{{tableName}}'\",\n    empty_field_name:\n      \"Nincs megadva egy mező `neve` a(z) '{{tableName}}' táblában\",\n    empty_field_type:\n      \"Nincs megadva egy mező `típusa` a(z) '{{tableName}}' táblában\",\n    no_values_for_field:\n      \"A(z) '{{tableName}}' tábla '{{fieldName}}' mezője `{{type}}` típusú, de nincs megadva érték\",\n    default_doesnt_match_type:\n      \"A(z) '{{tableName}}' tábla '{{fieldName}}' mezőjének alapértelmezett értéke nem egyezik a mező típusával\",\n    not_null_is_null:\n      \"A(z) '{{tableName}}' tábla '{{fieldName}}' mezője NOT NULL-ként van beállítva, de a megadott alapért. érték NULL\",\n    duplicate_fields:\n      \"Több '{{fieldName}}' nevű mező is létezik a(z) '{{tableName}}' táblában\",\n    duplicate_index:\n      \"Több '{{indexName}}' nevű index is létezik a(z) '{{tableName}}' táblában\",\n    empty_index:\n      \"A(z) '{{tableName}}' táblában levő index egyetlen oszlopot sem indexel\",\n    no_primary_key:\n      \"A(z) '{{tableName}}' tábla nem rendelkezik elsődleges kulccsal\",\n    type_with_no_name: \"Nincs megadva egy egyedi típus neve\",\n    duplicate_types: \"Több típus is létezik a(z) '{{typeName}}' névvel\",\n    type_w_no_fields: \"Nincs megadva mező a(z) '{{typeName}}' típusnak\",\n    empty_type_field_name: \"Nincs megadva a(z) '{{typeName}}' típus `neve`\",\n    empty_type_field_type: \"Nincs megadva a(z) '{{typeName}}' típus `típusa`\",\n    no_values_for_type_field:\n      \"A(z) '{{typeName}}' típus '{{fieldName}}' mezője `{{type}}` típusú, de nincs megadva érték\",\n    duplicate_type_fields:\n      \"Több '{{fieldName}}' nevű mező is létezik a(z) '{{typeName}}' típussal\",\n    duplicate_reference: \"Több hivatkozás is létezik a(z) '{{refName}}' névvel\",\n    circular_dependency:\n      \"Körkörös hivatkozás a(z) '{{refName}}' táblával kapcsolatban\",\n    timeline: \"Előzmények\",\n    priority: \"Prioritás\",\n    none: \"Nincs\",\n    low: \"Alacsony\",\n    medium: \"Közepes\",\n    high: \"Magas\",\n    sort_by: \"Rendezés\",\n    my_order: \"Saját sorrend\",\n    completed: \"Befejezetlenek elöl\",\n    alphabetically: \"ABC sorrend\",\n    add_task: \"Új feladat\",\n    details: \"Részletek\",\n    no_tasks: \"Nincs teendő.\",\n    no_activity: \"Még nem történt módosítás.\",\n    move_element: \"{{name}} mozgatása a {{coords}} koordinátákra\",\n    edit_area: \"{{extra}} {{areaName}} terület szerkesztése\",\n    delete_area: \"{{areaName}} terület törlése\",\n    edit_note: \"{{extra}} {{noteTitle}} jegyzet szerkesztése\",\n    delete_note: \"{{noteTitle}} jegyzet törlése\",\n    edit_table: \"{{extra}} {{tableName}} tábla szerkesztése\",\n    delete_table: \"{{tableName}} tábla törlése\",\n    edit_type: \"{{extra}} {{typeName}} típus szerkesztése\",\n    delete_type: \"{{typeName}} típus törlése\",\n    add_relationship: \"Új kapcsolat\",\n    edit_relationship: \"{{extra}} {{refName}} kapcsolat szerkesztése\",\n    delete_relationship: \"{{refName}} kapcsolat törlése\",\n    not_found: \"Nincs találat\",\n    pick_db: \"Válasszon adatbázist\",\n    generic: \"Általános\",\n    generic_description:\n      \"Az általános diagramok bármilyen fajta SQL-be exportálhatóak, de kevés adattípust támogatnak.\",\n    enums: \"Enum-ok\",\n    add_enum: \"Új enum\",\n    edit_enum: \"{{extra}} {{enumName}} enum szerkesztése\",\n    delete_enum: \"Enum törlése\",\n    enum_w_no_name: \"Egy enum-nak nincs megadva név\",\n    enum_w_no_values: \"A(z) '{{enumName}}' enum-ban nincs megadva érték\",\n    duplicate_enums: \"Több enum is létezik a(z) '{{enumName}}' névvel\",\n    enum_deleted: \"Enum törölve\",\n    no_enums: \"Nincs enum\",\n    no_enums_text: \"Itt adhat meg enum-okat\",\n    declare_array: \"Tömb megadása\",\n    empty_index_name:\n      \"A(z) '{{tableName}}' táblában egy indexnek nincs megadva név\",\n    didnt_find_diagram: \"Hoppá! A diagram nem található.\",\n    unsigned: \"Előjel nélküli\",\n    share: \"Megosztás\",\n    unshare: \"Megosztás megszüntetése\",\n    copy_link: \"Hivatkozás másolása\",\n    readme: \"OLVASS_EL\",\n    failed_to_load:\n      \"A betöltés sikertelen. Ellenőrizze a hivatkozás helyességét!\",\n    share_info:\n      \"* Ezen hivatkozás megosztása nem fog létrehozni élő, valósidejű együttműködési munkamenetet.\",\n    show_relationship_labels: \"Kapcsolatcímkék\",\n    docs: \"Dokumentáció\",\n    supported_types: \"Támogatott fájltípusok:\",\n    bulk_update: \"Csoportos frissítés\",\n    multiselect: \"Csoportos kijelölés\",\n    export_saved_data: \"Mentett adatok exportálása\",\n    dbml_view: \"DBML nézet\",\n    tab_view: \"Lap nézet\",\n    label: \"Címke\",\n    many_side_label: \"A 'több' (n) oldal címkéje\",\n    version: \"Verzió\",\n    versions: \"Verziók\",\n    no_saved_versions: \"Nincs mentett verzió\",\n    record_version: \"Verzió felvétele\",\n    commited_at: \"Hozzáadva:\",\n    read_only: \"Csak olvasható\",\n    continue: \"Folytatás\",\n    restore_version: \"Verzió visszaállítása\",\n    restore_warning: \"Másik verzió betöltése felül fog írni minden változtatást.\",\n    return_to_current: \"Visszatérés a diagramra\",\n    no_changes_to_record: \"Nincs felvehető változás\",\n    click_to_view: \"Kattintson a megtekintéshez\",\n    load_more: \"Továbbiak betöltése\",\n    clear_cache: \"Gyorsítótár ürítése\",\n    cache_cleared: \"A gyorsítótár ürítve\",\n    failed_to_record_version: \"A verzió felvétele sikertelen\",\n    failed_to_load_diagram: \"A diagram betöltése sikertelen\",\n    see_all: \"Mind megtekintése\",\n    insert_sql: \"SQL beszúrása\",\n    upload_file: \"Fájl feltöltése\",\n  },\n};\n\nexport { hu, hungarian };\n"
  },
  {
    "path": "src/i18n/locales/hy.js",
    "content": "const armenian = {\n  name: \"Armenian\",\n  native_name: \"Հայերեն\",\n  code: \"hy\",\n};\n\nconst hy = {\n  translation: {\n    report_bug: \"Զեկուցել սխալի մասին\",\n    import_from: \"Ներմուծել\",\n    import: \"Ներմուծել\",\n    file: \"Ֆայլ\",\n    new: \"Նոր\",\n    new_window: \"Նոր պատուհան\",\n    open: \"Բացել\",\n    save: \"Պահպանել\",\n    save_as: \"Պահպանել որպես\",\n    save_as_template: \"Պահպանել որպես ձևանմուշ\",\n    template_saved: \"Ձևանմուշը պահպանվաձ է\",\n    rename: \"Վերանվանել\",\n    delete_diagram: \"Ջնջել սխեման\",\n    are_you_sure_delete_diagram:\n      \"Վստա՞հ եք, որ ցանկանում եք ջնջել այս սխեման։ Այս գործողությունը անդառնալի է։\",\n    oops_smth_went_wrong: \"Ուֆֆ, չստացվեց\",\n    import_diagram: \"Ներմուծել սխեման\",\n    import_from_source: \"Ներմուծել SQL-ից\",\n    export_as: \"Արտահանել որպես\",\n    export_source: \"Արտահանել SQL\",\n    models: \"Մոդելներ\",\n    exit: \"Ելք\",\n    edit: \"Խմբագրել\",\n    undo: \"Հետարկել\",\n    redo: \"Կրկնել\",\n    clear: \"Դատարկել\",\n    are_you_sure_clear:\n      \"Վստա՞հ եք, որ ցանկանում եք դատարկել սխեման։ Այս գործողությունը անդառնալի է։\",\n    cut: \"Կտրել\",\n    copy: \"Պատճենել\",\n    paste: \"Տեղադրել\",\n    duplicate: \"Կրկնօրինակել\",\n    delete: \"Ջնջել\",\n    copy_as_image: \"Պատճենել որպես նկար\",\n    view: \"Տեսք\",\n    header: \"Մենյուի գոտի\",\n    sidebar: \"Կողմնագոտի\",\n    issues: \"Խնդիրներ\",\n    presentation_mode: \"Ներկայացման ռեժիմ\",\n    strict_mode: \"Խիստ ռեժիմ\",\n    field_details: \"Դաշտի մանրամասներ\",\n    reset_view: \"Վերականգնել տեսքը\",\n    show_grid: \"Ցուցադրել ցանցը\",\n    show_cardinality: \"Ցուցադրել կարդինալությունը\",\n    theme: \"Ֆոն\",\n    light: \"Լուսավոր\",\n    dark: \"Մութ\",\n    zoom_in: \"Մեծացնել\",\n    zoom_out: \"Փոքրացնել\",\n    fullscreen: \"Լիաէկրան\",\n    settings: \"Կարգավորումներ\",\n    show_timeline: \"Պատմություն\",\n    autosave: \"Ավտոմատ պահպանել\",\n    panning: \"Շարժել սխեման\",\n    show_debug_coordinates: \"Ցուցադրել կոորդինատները\",\n    transform: \"Փոփոխություն\",\n    viewbox: \"Դիտման գոտի\",\n    cursor_coordinates: \"Կուրսորի կոորդինատներ\",\n    coordinate_space: \"Տարածք\",\n    coordinate_space_screen: \"Էկրան\",\n    coordinate_space_diagram: \"Սխեմա\",\n    table_width: \"Աղյուսակի լայնություն\",\n    language: \"Լեզու\",\n    flush_storage: \"Դատարկել պահեստը\",\n    are_you_sure_flush_storage:\n      \"Վստա՞հ եք, որ ցանկանում եք մաքրել պահոցը։ Սա անդառնալիորեն կհեռացնի ձեր բոլոր սխեմաներն ու ձևանմուշները։\",\n    storage_flushed: \"Պահեստը դատարկված է\",\n    help: \"Օգնություն\",\n    shortcuts: \"Դյուրանցումներ\",\n    ask_on_discord: \"Հարցնել Discord-ում\",\n    feedback: \"Հետադարձ կապ\",\n    no_changes: \"Փոփոխություններ չկան\",\n    loading: \"Բեռնվում է...\",\n    last_saved: \"Վերջին պահպանումը\",\n    saving: \"Պահպանվում է...\",\n    failed_to_save: \"Չհաջողվեց պահպանել\",\n    fit_window_reset: \"Հարմարեցնել պատուհանին\",\n    zoom: \"Մեծացնել\",\n    add_table: \"Նոր աղյուսակ\",\n    add_area: \"Ներ մակերես\",\n    add_note: \"Նոր նշում\",\n    add_type: \"Նոր տիպ\",\n    to_do: \"Առաջադրանքներ\",\n    tables: \"Աղյուսակներ\",\n    relationships: \"Հարաբերություններ\",\n    subject_areas: \"Կազմակերպման մակերեսներ\",\n    notes: \"Նշումներ\",\n    types: \"Տիպեր\",\n    search: \"Փնտրել...\",\n    no_tables: \"Աղյուսակներ չկան\",\n    no_tables_text: \"Սկսեք կառուցել ձեր սխեման\",\n    no_relationships: \"Հարաբերություններ չկան\",\n    no_relationships_text:\n      \"Քաշեք և միացրեք դաշտերը հարաբերություններ ստեղծելու համար\",\n    no_subject_areas: \"Կազմակերպման մակերեսներ չկան\",\n    no_subject_areas_text:\n      \"Ավելացրեք Կազմակերպման մակերեսներ աղյուսակները խմբավորելու համար\",\n    no_notes: \"Նշումներ չկան\",\n    no_notes_text:\n      \"Օգտագործեք նշումները լրացուցիչ տեղեկություններ գրանցելու համար\",\n    no_types: \"Տիպեր չկան\",\n    no_types_text: \"Ստեղծեք ձեր սեփական տվյալների տիպերը\",\n    no_issues: \"Խնդիրներ չկան\",\n    strict_mode_is_on_no_issues:\n      \"Խիստ ռեժիմը միցված է, ուստի խնդիրներ չեն ցուցադրվի։\",\n    name: \"Անուն\",\n    type: \"Տիպ\",\n    null: \"Null\",\n    not_null: \"Not null\",\n    primary: \"Primary\",\n    unique: \"Unique\",\n    autoincrement: \"Autoincrement\",\n    default_value: \"Default\",\n    check: \"Check արտահայտություն\",\n    this_will_appear_as_is: \"*Սա կհայտնվի գեներացված կոդում հենց այսպես։\",\n    comment: \"Մեկնաբանություն\",\n    add_field: \"Նոր դաշտ\",\n    values: \"Արժեքներ\",\n    size: \"Չափ\",\n    precision: \"Ճշտություն\",\n    set_precision: \"Սահմանել ճշտություն՝ (չափ, թվանշաններ)\",\n    use_for_batch_input: \"Օգտագործեք , խմբային ներմուծման համար\",\n    indices: \"Ինդեքսներ\",\n    add_index: \"Նոր ինդեքս\",\n    select_fields: \"Ընտրել դաշտեր\",\n    title: \"Վերնագիր\",\n    not_set: \"Չսահմանված\",\n    foreign: \"Foreign\",\n    cardinality: \"Կարդինալություն\",\n    on_update: \"Թարմացնելիս\",\n    on_delete: \"Ջնջելիս\",\n    swap: \"Փոխանակել\",\n    one_to_one: \"Մեկից մեկ\",\n    one_to_many: \"Մեկից շատ\",\n    many_to_one: \"Շատից մեկ\",\n    content: \"Բովանդակություն\",\n    types_info:\n      \"Այս ֆունկցիան նախատեսված է օբյեկտ-ռելյացիոն DBMS-ների համար, ինչպիսիք են PostgreSQL-ը։\\nԵթե օգտագործվի MySQL կամ MariaDB համար, կգեներացվի JSON տեսակ համապատասխան json վավերացման ստուգումով։\\nԵթե օգտագործվի SQLite-ի համար, այն կթարգմանվի BLOB-ի։\\nԵթե օգտագործվի MSSQL-ի համար, կգեներացվի առաջին դաշտի տեսակալիաս։\",\n    table_deleted: \"Աղյուսակը ջնջված է\",\n    area_deleted: \"Մակերեսը ջհջված է\",\n    note_deleted: \"Նմուշը ջհջված է\",\n    relationship_deleted: \"Հարաբերությունը ջնջված է\",\n    type_deleted: \"Տիպը ջհջված է\",\n    cannot_connect: \"Չի հաջողվում միացնել, դաշտորը տարբեր տեսակներ ունեն\",\n    copied_to_clipboard: \"Պատճենված է սեղմակապին\",\n    create_new_diagram: \"Ստեղծել նոր սխեմա\",\n    cancel: \"Չեղարկել\",\n    open_diagram: \"Բացել սխեմա\",\n    rename_diagram: \"Վերանվանել սխեման\",\n    export: \"Արտահանել\",\n    export_image: \"Արտահանել պատկերը\",\n    create: \"Ստեղծել\",\n    confirm: \"Հաստատել\",\n    last_modified: \"Վերջին փոփոխությունը\",\n    drag_and_drop_files:\n      \"Քաշեք և թողեք ֆայլը այստեղ կամ սեղմեք բեռնելու համար։\",\n    upload_sql_to_generate_diagrams:\n      \"Վերբեռնեք sql ֆայլ՝ ձեր աղյուսակներն ու սյունակները ավտոմատ ստեղծելու համար։\",\n    overwrite_existing_diagram: \"Փոխարինել առկա սխեման\",\n    only_mysql_supported: \"\",\n    blank: \"Դատարկ\",\n    filename: \"Ֆայլի անուն\",\n    table_w_no_name: \"Հայտարարվել է աղյուսակ առանց անվան\",\n    duplicate_table_by_name: \"Կրկնօրինակված աղյուսակ '{{tableName}}' անվամբ\",\n    empty_field_name: \"Դատարկ դաշտ 'name' '{{tableName}}' աղյուսակում\",\n    empty_field_type: \"Դատարկ դաշտ 'type' '{{tableName}}' աղյուսակում\",\n    no_values_for_field:\n      \"'{{fieldName}}' դաշտը '{{tableName}}' աղյուսակում `{{type}}` տեսակի է, բայց արժեքներ չեն նշվել\",\n    default_doesnt_match_type:\n      \"Default արժեքը '{{tableName}}' աղյուսակի '{{fieldName}}' դաշտում չի համընկնում իր տեսակի հետ\",\n    not_null_is_null:\n      \"'{{fieldName}}' դաշտ '{{tableName}}' աղյուսակում NOT NULL է, բայց default NULL է\",\n    duplicate_fields:\n      \"Կրկնօրինակված դաշտեր '{{fieldName}}' անվամբ '{{tableName}}' աղյուսակում\",\n    duplicate_index:\n      \"Կրկնօրինակված ինդեքս '{{indexName}}' անվամբ '{{tableName}}' աղյուսակում\",\n    empty_index: \"Ինդեքս '{{tableName}}' աղյուսակում չի ընդգրկում սյունակներ\",\n    no_primary_key: \"'{{tableName}}' աղյուսակը չունի հիմնական բանալի\",\n    type_with_no_name: \"Հայտարարվել է տիպ առանց անվան\",\n    duplicate_types: \"Կրկնօրինակված տիպ '{{typeName}}' անվամբ\",\n    type_w_no_fields:\n      \"Հայտարարվել է դատարկ տիպ '{{typeName}}' անվամբ առանց դաշտերի\",\n    empty_type_field_name: \"Դատարկ դաշտ 'name' '{{typeName}}' տիպում\",\n    empty_type_field_type: \"Դատարկ դաշտ 'type' '{{typeName}}' տիպում\",\n    no_values_for_type_field:\n      \"'{{fieldName}}' դաշտ '{{typeName}}' տիպում 'type' տիպի է, բայց արժեքներ չեն նշվել\",\n    duplicate_type_fields:\n      \"Կրկնօրինակված դաշտեր '{{fieldName}}' անվամբ '{{typeName}}' տիպում\",\n    duplicate_reference: \"Կրկնօրինակված հղում '{{refName}}' անվամբ\",\n    circular_dependency: \"Շրջանաձև կախվածություն '{{refName}}' աղյուսակում\",\n    timeline: \"Ժամանակացույց\",\n    priority: \"Առաջնահերթություն\",\n    none: \"Ոչ մի\",\n    low: \"Ցածր\",\n    medium: \"Միջին\",\n    high: \"Բարձր\",\n    sort_by: \"Տեսակավորել ըստ՝\",\n    my_order: \"Իմ կարգ\",\n    completed: \"Ավարտված\",\n    alphabetically: \"Այբբենական\",\n    add_task: \"Ավելացնել առաջադրանք\",\n    details: \"Մանրամասներ\",\n    no_tasks: \"Դուք դեռ չունեք առաջադրանքներ։\",\n    no_activity: \"Դուք դեռ չունեք գործողություններ։\",\n    move_element: \"Տեղափոխել {{name}} {{coords}}-ում\",\n    edit_area: \"{{extra}} Խմբագրել մակերես {{areaName}}\",\n    delete_area: \"Ջնջել մակերես {{areaName}}\",\n    edit_note: \"{{extra}} Խմբագրել նշում {{noteTitle}}\",\n    delete_note: \"Ջնջել նշում {{noteTitle}}\",\n    edit_table: \"{{extra}} Խմբագրել աղյուսակ {{tableName}}\",\n    delete_table: \"Ջնջել աղյուսակ {{tableName}}\",\n    edit_type: \"{{extra}} Խմբագրել  {{typeName}}\",\n    delete_type: \"Ջնջել  {{typeName}}\",\n    add_relationship: \"Ավելացնել հարաբերություն\",\n    edit_relationship: \"{{extra}} Խմբագրել հարաբերություն {{refName}}\",\n    delete_relationship: \"Ջնջել հարաբերություն {{refName}}\",\n    not_found: \"Չի գտնվել\",\n    pick_db: \"Ընտրեք տվյալների բազան\",\n    generic: \"Ընդհանուր\",\n    generic_description:\n      \"Ընդհանուր սխեմաները կարող են արտահանվել ցանկացած SQL տիպի, բայց աջակցում են քիչ տվյալների տեսակներ։\",\n    enums: \"Enum-ներ\",\n    add_enum: \"Ավելացնել enum\",\n    edit_enum: \"{{extra}} Խմբագրել enum {{enumName}}\",\n    delete_enum: \"Ջնջել enum\",\n    enum_w_no_name: \"Հայտնաբերվել է enum առանց անվան\",\n    enum_w_no_values: \"Հայտնաբերվել է enum '{{enumName}}' առանց արժեքների\",\n    duplicate_enums: \"Կրկնօրինակված enum '{{enumName}}' անվամբ\",\n    no_enums: \"Enum-ներ չկան\",\n    no_enums_text: \"Սահմանեք enum-ները այստեղ\",\n    declare_array: \"Հայտարարել array\",\n    empty_index_name:\n      \"Հայտարարվել է ինդեքս '{{tableName}}' աղյուսակում առանց անվան\",\n    didnt_find_diagram: \"Ուֆֆ! Սխեման չի գտնվել։\",\n  },\n};\n\nexport { hy, armenian };\n"
  },
  {
    "path": "src/i18n/locales/id.js",
    "content": "const indonesian = {\n  name: \"Indonesian\",\n  native_name: \"Bahasa Indonesia\",\n  code: \"id\",\n};\n\nconst id = {\n  translation: {\n    report_bug: \"Laporkan bug\",\n    import_from: \"Impor\",\n    import: \"Impor\",\n    file: \"Berkas\",\n    new: \"Baru\",\n    new_window: \"Jendela baru\",\n    open: \"Buka\",\n    save: \"Simpan\",\n    save_as: \"Simpan sebagai\",\n    save_as_template: \"Simpan sebagai template\",\n    template_saved: \"Template tersimpan!\",\n    rename: \"Ubah nama\",\n    delete_diagram: \"Hapus diagram\",\n    are_you_sure_delete_diagram:\n      \"Apakah Anda yakin ingin menghapus diagram ini? Operasi ini tidak bisa dibatalkan.\",\n    oops_smth_went_wrong: \"Ups! Ada yang salah.\",\n    import_diagram: \"Impor diagram\",\n    import_from_source: \"Impor dari SQL\",\n    export_as: \"Ekspor sebagai\",\n    export_source: \"Ekspor SQL\",\n    models: \"Model\",\n    exit: \"Keluar\",\n    edit: \"Sunting\",\n    undo: \"Batalkan\",\n    redo: \"Ulangi\",\n    clear: \"Bersihkan\",\n    are_you_sure_clear:\n      \"Apakah Anda yakin ingin membersihkan diagram ini? Ini tidak bisa dibatalkan.\",\n    cut: \"Potong\",\n    copy: \"Salin\",\n    paste: \"Tempel\",\n    duplicate: \"Gandakan\",\n    delete: \"Hapus\",\n    copy_as_image: \"Salin sebagai gambar\",\n    view: \"Tampilan\",\n    header: \"Bilah Menu\",\n    sidebar: \"Bilah Samping\",\n    issues: \"Masalah\",\n    presentation_mode: \"Mode presentasi\",\n    strict_mode: \"Mode ketat\",\n    field_details: \"Detail bidang\",\n    reset_view: \"Atur ulang tampilan\",\n    show_grid: \"Tampilkan grid\",\n    snap_to_grid: \"Sejajarkan ke grid\",\n    show_cardinality: \"Tampilkan kardinalitas\",\n    show_relationship_labels: \"Tampilkan label hubungan\",\n    theme: \"Tema\",\n    light: \"Terang\",\n    dark: \"Gelap\",\n    zoom_in: \"Perbesar\",\n    zoom_out: \"Perkecil\",\n    fullscreen: \"Layar penuh\",\n    settings: \"Pengaturan\",\n    show_timeline: \"Tampilkan garis waktu\",\n    autosave: \"Simpan otomatis\",\n    panning: \"Geser\",\n    show_debug_coordinates: \"Tampilkan koordinat debug\",\n    transform: \"Transformasi\",\n    viewbox: \"Kotak tampilan\",\n    cursor_coordinates: \"Koordinat kursor\",\n    coordinate_space: \"Ruang\",\n    coordinate_space_screen: \"Layar\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Lebar tabel\",\n    language: \"Bahasa\",\n    flush_storage: \"Bersihkan penyimpanan\",\n    are_you_sure_flush_storage:\n      \"Apakah Anda yakin ingin membersihkan penyimpanan? Ini akan menghapus semua diagram dan template kustom Anda secara permanen.\",\n    storage_flushed: \"Penyimpanan dibersihkan\",\n    export_saved_data: \"Ekspor data yang disimpan\",\n    clear_cache: \"Bersihkan cache\",\n    help: \"Bantuan\",\n    docs: \"Dokumentasi\",\n    shortcuts: \"Pintasan\",\n    ask_on_discord: \"Tanya kami di Discord\",\n    feedback: \"Umpan balik\",\n    no_changes: \"Tidak ada perubahan\",\n    loading: \"Memuat...\",\n    last_saved: \"Terakhir disimpan\",\n    saving: \"Menyimpan...\",\n    failed_to_save: \"Gagal menyimpan\",\n    fit_window_reset: \"Sesuaikan jendela / Atur ulang\",\n    zoom: \"Zoom\",\n    add_table: \"Tambah tabel\",\n    add_area: \"Tambah area\",\n    add_note: \"Tambah catatan\",\n    add_type: \"Tambah tipe\",\n    to_do: \"Yang harus dilakukan\",\n    tables: \"Tabel\",\n    relationships: \"Hubungan\",\n    subject_areas: \"Area subjek\",\n    notes: \"Catatan\",\n    types: \"Jenis\",\n    search: \"Cari...\",\n    no_tables: \"Tidak ada tabel\",\n    no_tables_text: \"Mulai bangun diagram Anda!\",\n    no_relationships: \"Tidak ada hubungan\",\n    no_relationships_text:\n      \"Seret untuk menghubungkan bidang dan membentuk hubungan!\",\n    no_subject_areas: \"Tidak ada area subjek\",\n    no_subject_areas_text: \"Tambahkan area subjek untuk mengelompokkan tabel!\",\n    no_notes: \"Tidak ada catatan\",\n    no_notes_text: \"Gunakan catatan untuk mencatat informasi tambahan\",\n    no_types: \"Tidak ada tipe\",\n    no_types_text: \"Buat tipe data kustom Anda sendiri\",\n    no_issues: \"Tidak ada masalah yang terdeteksi.\",\n    strict_mode_is_on_no_issues:\n      \"Mode ketat dimatikan sehingga tidak ada masalah yang akan ditampilkan.\",\n    name: \"Nama\",\n    type: \"Jenis\",\n    null: \"Kosong\",\n    not_null: \"Tidak kosong\",\n    primary: \"Utama\",\n    unique: \"Unik\",\n    autoincrement: \"Autoincrement\",\n    default_value: \"Nilai default\",\n    check: \"Periksa ekspresi\",\n    this_will_appear_as_is:\n      \"*Ini akan muncul dalam skrip yang dihasilkan sebagaimana adanya.\",\n    comment: \"Komentar\",\n    add_field: \"Tambah bidang\",\n    values: \"Nilai\",\n    size: \"Ukuran\",\n    precision: \"Presisi\",\n    set_precision: \"Atur presisi: (ukuran, digit)\",\n    use_for_batch_input: \"Gunakan , untuk input batch\",\n    indices: \"Indeks\",\n    add_index: \"Tambah indeks\",\n    select_fields: \"Pilih bidang\",\n    title: \"Judul\",\n    not_set: \"Belum diatur\",\n    foreign: \"Asing\",\n    cardinality: \"Kardinalitas\",\n    on_update: \"Pada pembaruan\",\n    on_delete: \"Pada penghapusan\",\n    swap: \"Tukar\",\n    one_to_one: \"Satu ke satu\",\n    one_to_many: \"Satu ke banyak\",\n    many_to_one: \"Banyak ke satu\",\n    content: \"Konten\",\n    types_info:\n      \"Fitur ini ditujukan untuk DBMS objek-relasional seperti PostgreSQL.\\nJika digunakan untuk MySQL atau MariaDB, tipe JSON akan dihasilkan dengan validasi json yang sesuai.\\nJika digunakan untuk SQLite, itu akan diterjemahkan menjadi BLOB.\\nJika digunakan untuk MSSQL, alias tipe ke bidang pertama akan dihasilkan.\",\n    table_deleted: \"Tabel dihapus\",\n    area_deleted: \"Area dihapus\",\n    note_deleted: \"Catatan dihapus\",\n    relationship_deleted: \"Hubungan dihapus\",\n    type_deleted: \"Jenis dihapus\",\n    cannot_connect:\n      \"Tidak dapat menghubungkan, kolom memiliki tipe yang berbeda\",\n    copied_to_clipboard: \"Disalin ke papan klip\",\n    create_new_diagram: \"Buat diagram baru\",\n    cancel: \"Batal\",\n    open_diagram: \"Buka diagram\",\n    rename_diagram: \"Ubah nama diagram\",\n    export: \"Ekspor\",\n    export_image: \"Ekspor gambar\",\n    create: \"Buat\",\n    confirm: \"Konfirmasi\",\n    last_modified: \"Terakhir diubah\",\n    drag_and_drop_files:\n      \"Seret dan lepas file di sini atau klik untuk mengunggah.\",\n    upload_sql_to_generate_diagrams:\n      \"Unggah file SQL untuk mengotomatiskan tabel dan kolom Anda.\",\n    overwrite_existing_diagram: \"Timpa diagram yang ada\",\n    only_mysql_supported: \"*Saat ini hanya memuat skrip MySQL yang didukung.\",\n    blank: \"Kosong\",\n    filename: \"Nama file\",\n    table_w_no_name: \"Mendeklarasikan tabel tanpa nama\",\n    duplicate_table_by_name: \"Tabel duplikat dengan nama '{{tableName}}'\",\n    empty_field_name: \"Nama bidang `name` kosong dalam tabel '{{tableName}}'\",\n    empty_field_type: \"Jenis bidang `type` kosong dalam tabel '{{tableName}}'\",\n    no_values_for_field:\n      \"Bidang '{{fieldName}}' dalam tabel '{{tableName}}' adalah tipe `{{type}}` tetapi tidak ada nilai yang ditentukan\",\n    default_doesnt_match_type:\n      \"Nilai default untuk bidang '{{fieldName}}' dalam tabel '{{tableName}}' tidak sesuai dengan tipenya\",\n    not_null_is_null:\n      \"Bidang '{{fieldName}}' dalam tabel '{{tableName}}' adalah TIDAK NULL tetapi memiliki nilai default NULL\",\n    duplicate_fields:\n      \"Bidang tabel duplikat dengan nama '{{fieldName}}' dalam tabel '{{tableName}}'\",\n    duplicate_index:\n      \"Indeks duplikat dengan nama '{{indexName}}' dalam tabel '{{tableName}}'\",\n    empty_index:\n      \"Indeks dalam tabel '{{tableName}}' tidak mengindeks kolom apapun\",\n    no_primary_key: \"Tabel '{{tableName}}' tidak memiliki kunci utama\",\n    type_with_no_name: \"Mendeklarasikan tipe tanpa nama\",\n    duplicate_types: \"Tipe duplikat dengan nama '{{typeName}}'\",\n    type_w_no_fields: \"Mendeklarasikan tipe '{{typeName}}' kosong tanpa bidang\",\n    empty_type_field_name:\n      \"Nama bidang `name` kosong dalam tipe '{{typeName}}'\",\n    empty_type_field_type:\n      \"Jenis bidang `type` kosong dalam tipe '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Bidang '{{fieldName}}' dalam tipe '{{typeName}}' adalah tipe `{{type}}` tetapi tidak ada nilai yang ditentukan\",\n    duplicate_type_fields:\n      \"Bidang tipe duplikat dengan nama '{{fieldName}}' dalam tipe '{{typeName}}'\",\n    duplicate_reference: \"Referensi duplikat dengan nama '{{refName}}'\",\n    circular_dependency:\n      \"Ketergantungan siklik yang melibatkan tabel '{{refName}}'\",\n    timeline: \"Garis waktu\",\n    priority: \"Prioritas\",\n    none: \"Tidak ada\",\n    low: \"Rendah\",\n    medium: \"Sedang\",\n    high: \"Tinggi\",\n    sort_by: \"Urutkan berdasarkan\",\n    my_order: \"Urutan saya\",\n    completed: \"Selesai\",\n    alphabetically: \"Alfabet\",\n    add_task: \"Tambah tugas\",\n    details: \"Detail\",\n    no_tasks: \"Anda belum memiliki tugas.\",\n    no_activity: \"Anda belum memiliki aktivitas.\",\n    move_element: \"Pindahkan {{name}} ke {{coords}}\",\n    edit_area: \"{{extra}} Edit area {{areaName}}\",\n    delete_area: \"Hapus area {{areaName}}\",\n    edit_note: \"{{extra}} Edit catatan {{noteTitle}}\",\n    delete_note: \"Hapus catatan {{noteTitle}}\",\n    edit_table: \"{{extra}} Edit tabel {{tableName}}\",\n    delete_table: \"Hapus tabel {{tableName}}\",\n    edit_type: \"{{extra}} Edit tipe {{typeName}}\",\n    delete_type: \"Hapus tipe {{typeName}}\",\n    add_relationship: \"Tambah hubungan\",\n    edit_relationship: \"{{extra}} Edit hubungan {{refName}}\",\n    delete_relationship: \"Hapus hubungan {{refName}}\",\n    not_found: \"Tidak ditemukan\",\n    pick_db: \"Pilih basis data\",\n    generic: \"Generik\",\n    generic_description:\n      \"Diagram generik dapat diekspor ke SQL mana pun tetapi mendukung sedikit tipe data.\",\n    enums: \"Enums\",\n    add_enum: \"Tambah enum\",\n    edit_enum: \"{{extra}} Edit enum {{enumName}}\",\n    delete_enum: \"Hapus enum\",\n    enum_w_no_name: \"Menemukan enum tanpa nama\",\n    enum_w_no_values: \"Menemukan enum '{{enumName}}' tanpa nilai\",\n    duplicate_enums: \"Enum duplikat dengan nama '{{enumName}}'\",\n    no_enums: \"Tidak ada enum\",\n    no_enums_text: \"Definisikan enum di sini\",\n    declare_array: \"Deklarasikan array\",\n    empty_index_name:\n      \"Mendeklarasikan indeks tanpa nama dalam tabel '{{tableName}}'\",\n    didnt_find_diagram: \"Ups! Tidak menemukan diagram.\",\n    dbml_view: \"Tampilan DBML\",\n  },\n};\n\nexport { id, indonesian };\n"
  },
  {
    "path": "src/i18n/locales/it.js",
    "content": "const italian = {\n  name: \"Italian\",\n  native_name: \"Italiano\",\n  code: \"it\",\n};\n\nconst it = {\n  translation: {\n    report_bug: \"Segnalare un bug\",\n    import_from: \"Importa\",\n    import: \"Importa\",\n    file: \"File\",\n    new: \"Nuovo\",\n    new_window: \"Nuova Finestra\",\n    open: \"Apri\",\n    save: \"Salva\",\n    save_as: \"Salva come\",\n    save_as_template: \"Salva come modello\",\n    template_saved: \"Modello salvato!\",\n    rename: \"Rinomina\",\n    delete_diagram: \"Elimina diagramma\",\n    are_you_sure_delete_diagram:\n      \"Sei sicuro di voler eliminare il diagramma? L'operazione è irreversibile.\",\n    oops_smth_went_wrong: \"Oops! Qualcosa è andato storto.\",\n    import_diagram: \"Importa diagramma\",\n    import_from_source: \"Importa da SQL\",\n    export_as: \"Esporta come\",\n    export_source: \"Esporta SQL\",\n    models: \"Modelli\",\n    exit: \"Esci\",\n    edit: \"Modifica\",\n    undo: \"Annulla\",\n    redo: \"Ripristina\",\n    clear: \"Resetta\",\n    are_you_sure_clear:\n      \"Sei sicuro di voler resettare il diagramma? L'operazione è irreversibile.\",\n    cut: \"Taglia\",\n    copy: \"Copia\",\n    paste: \"Incolla\",\n    duplicate: \"Duplica\",\n    delete: \"Elimina\",\n    copy_as_image: \"Copia come immagine\",\n    view: \"Visualizza\",\n    header: \"Intestazione\",\n    sidebar: \"Barra laterale\",\n    issues: \"Problemi\",\n    presentation_mode: \"Presentazione\",\n    strict_mode: \"Modalità strict\",\n    field_details: \"Dettagli sul campo\",\n    reset_view: \"Ristabilire vista\",\n    show_grid: \"Mostra griglia\",\n    snap_to_grid: \"Aggancia alla griglia\",\n    show_datatype: \"Mostra tipo di dato\",\n    show_cardinality: \"Mostra cardinalità\",\n    theme: \"Tema\",\n    light: \"Chiaro\",\n    dark: \"Scuro\",\n    zoom_in: \"Ingrandire\",\n    zoom_out: \"Rimpicciolire\",\n    fullscreen: \"Schermo intero\",\n    settings: \"Opzioni\",\n    show_timeline: \"Cronologia\",\n    autosave: \"Salvataggio automatico\",\n    panning: \"Panoramica\",\n    show_debug_coordinates: \"Mostra coordinate di debug\",\n    transform: \"Trasforma\",\n    viewbox: \"Visualizza Box\",\n    cursor_coordinates: \"Coordinate del cursore\",\n    coordinate_space: \"Spazio\",\n    coordinate_space_screen: \"Schermo\",\n    coordinate_space_diagram: \"Diagramma\",\n    table_width: \"Larghezza della tabella\",\n    language: \"Lingua\",\n    flush_storage: \"Pulizia memoria\",\n    are_you_sure_flush_storage:\n      \"Sei sicuro di voler eseguire la pulizia? L'operazione è irreversibile.\",\n    storage_flushed: \"Pulizia eseguita!\",\n    help: \"Aiuto\",\n    shortcuts: \"Scorciatoie\",\n    ask_on_discord: \"Contattaci su Discord\",\n    feedback: \"Feedback\",\n    no_changes: \"Nessun cambio\",\n    loading: \"Caricamento in corso…\",\n    last_saved: \"Ultimo salvataggio\",\n    saving: \"Salvataggio in corso… \",\n    failed_to_save: \"Errore durante il salvataggio\",\n    fit_window_reset: \"Adatta la finestra / Reimposta\",\n    zoom: \"Zoom\",\n    add_table: \"Aggiungi tabella\",\n    add_area: \"Aggiungi area\",\n    add_note: \"Aggiungi nota\",\n    add_type: \"Aggiungi tipo\",\n    to_do: \"Da fare\",\n    tables: \"Tabelle\",\n    relationships: \"Relazioni\",\n    subject_areas: \"Aree tematiche\",\n    notes: \"Note\",\n    types: \"Tipi\",\n    search: \"Cerca...\",\n    no_tables: \"Nessuna tabella\",\n    no_tables_text: \"Crea il tuo diagramma!\",\n    no_relationships: \"Nessuna relazione\",\n    no_relationships_text: \"Aggiungi una relazione tra tabelle!\",\n    no_subject_areas: \"Nessuna area tematica\",\n    no_subject_areas_text: \"Aggiungi un'area tematica!\",\n    no_notes: \"Nessuna nota\",\n    no_notes_text: \"Scrivi una nota!\",\n    no_types: \"Nessun tipo\",\n    no_types_text: \"Aggiungi un tipo!\",\n    no_issues: \"Nessun problema da segnalare\",\n    strict_mode_is_on_no_issues:\n      \"La modalità strict è disattivata, i problemi non verrano segnalati.\",\n    name: \"Nome\",\n    type: \"Tipo\",\n    null: \"Nullo\",\n    not_null: \"Non nullo\",\n    primary: \"Primario\",\n    unique: \"Unico\",\n    autoincrement: \"Autoincremento\",\n    default_value: \"Valore predefinito\",\n    check: \"Verifica l'espressione\",\n    this_will_appear_as_is: \"Questo apparirà nello script generato così com'è.\",\n    comment: \"Commento\",\n    add_field: \"Aggiungi campo\",\n    values: \"Valori\",\n    size: \"Dimensione\",\n    precision: \"Precisione\",\n    set_precision: \"Imposta precisione: 'dimensione, cifre'\",\n    use_for_batch_input: \"Usa, per l'elaborazione in batch\",\n    indices: \"Indici\",\n    add_index: \"Aggiungi indice\",\n    select_fields: \"Seleziona campo\",\n    title: \"Titolo\",\n    not_set: \"Non impostato\",\n    foreign: \"Esterno\",\n    cardinality: \"Cardinalità\",\n    on_update: \"Su aggiornamento\",\n    on_delete: \"Su eliminazione\",\n    swap: \"Scambiare\",\n    one_to_one: \"Uno a uno\",\n    one_to_many: \"Uno a molti\",\n    many_to_one: \"Molti a uno\",\n    content: \"Contenuto\",\n    types_info:\n      \"Questa funzione è destinata ai DBMS oggetto-relazionali, come PostgreSQL.\\nSe si usa per MySQL o MariaDB, verrà generato un tipo JSON con il corrispondente controllo di validazione json.\\nSe si usa per SQLite, verrà tradotto a BLOB.\\nSe si usa per MSSQL, verrà generato un alias di tipo nel primo campo.\",\n    table_deleted: \"Tabella rimossa\",\n    area_deleted: \"Area rimossa\",\n    note_deleted: \"Nota rimossa\",\n    relationship_deleted: \"Relazione rimossa\",\n    type_deleted: \"Tipo Rimosso\",\n    cannot_connect: \"Connessione non riuscita, le colonne hanno tipi diversi\",\n    copied_to_clipboard: \"Copiato negli appunti\",\n    create_new_diagram: \"Crea nuovo diagramma\",\n    cancel: \"Annulla\",\n    open_diagram: \"Apri diagramma\",\n    rename_diagram: \"Rinomina diagramma\",\n    export: \"Esporta\",\n    export_image: \"Esporta immagine\",\n    create: \"Crea\",\n    confirm: \"Accetta\",\n    last_modified: \"Ultima modifica\",\n    drag_and_drop_files:\n      \"Trascina e rilascia qui il file o clicca per caricarlo.\",\n    upload_sql_to_generate_diagrams:\n      \"Carica un file sql per autogenerare le tabelle e le colonne.\",\n    overwrite_existing_diagram: \"Sovrascrivi il diagramma esistente\",\n    only_mysql_supported:\n      \"*Per il momento è supportato solo il caricamento di script MySQL.\",\n    blank: \"In bianco\",\n    filename: \"Nome del file\",\n    table_w_no_name: \"Dichiarata una tabella senza nome\",\n    duplicate_table_by_name: \"Tabella duplicata con il nome '{{tableName}}'\",\n    empty_field_name: \"Campo `name` vuoto nella tabella '{{tableName}}'\",\n    empty_field_type: \"Campo `type` vuoto nella tabella '{{tableName}}'\",\n    no_values_for_field:\n      \"Il campo '{{fieldName}}' della tabella '{{tableName}}' è di tipo `{{type}}` ma non è stato specificato alcun valore\",\n    default_doesnt_match_type:\n      \"Il valore predefinito del campo '{{fieldName}}' della tabella '{{tableName}}' non corrisponde al suo tipo\",\n    not_null_is_null:\n      \"Il campo '{{fieldName}}' della tabella '{{tableName}}' è NOT NULL ma ha NULL come valore predefinito\",\n    duplicate_fields:\n      \"Campi della tabella duplicati con il nome '{{fieldName}}' nella tabella '{{tableName}}'\",\n    duplicate_index:\n      \"Indice duplicato con il nome '{{indexName}}' nella tabella '{{tableName}}'\",\n    empty_index: \"L'indice nella tabella '{{tableName}}' non indicizza nessuna colonna\",\n    no_primary_key: \"La tabella '{{tableName}}' non ha una chiave primaria\",\n    type_with_no_name: \"Dichiarato un tipo senza nome\",\n    duplicate_types: \"Tipi duplicati con il nome '{{typeName}}'\",\n    type_w_no_fields: \"Dichiarato un tipo vuoto '{{typeName}}' senza alcun campo\",\n    empty_type_field_name: \"Campo `name` vuoto nel tipo '{{typeName}}'\",\n    empty_type_field_type: \"Campo `type` vuoto nel tipo '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Il campo '{{fieldName}}' del tipo '{{typeName}}' è di tipo `{{type}}` ma non è stato specificato alcun valore\",\n    duplicate_type_fields:\n      \"Campi di tipo duplicati con il nome '{{fieldName}}' nel tipo '{{typeName}}'\",\n    duplicate_reference: \"Riferimento duplicato con il nome '{{refName}}'\",\n    circular_dependency: \"Dipendenza circolare riguardante la tabella '{{refName}}'\",\n    timeline: \"Cronologia\",\n    priority: \"Priorità\",\n    none: \"Nessuna\",\n    low: \"Bassa\",\n    medium: \"Media\",\n    high: \"Alta\",\n    sort_by: \"Ordinare per\",\n    my_order: \"Il mio ordine\",\n    completed: \"Completato\",\n    alphabetically: \"Alfabeticamente\",\n    add_task: \"Aggiungi compito\",\n    details: \"Dettagli\",\n    no_tasks: \"Non ci sono compiti da svolgere.\",\n    no_activity: \"Non ci sono ancora attività.\",\n    move_element: \"Muovi {{name}} a {{coords}}\",\n    edit_area: \"{{extra}} Modifica area {{areaName}}\",\n    delete_area: \"Elimina area {{areaName}}\",\n    edit_note: \"{{extra}} Modifica nota {{noteTitle}}\",\n    delete_note: \"Elimina nota {{noteTitle}}\",\n    edit_table: \"{{extra}} Modifica tabella {{tableName}}\",\n    delete_table: \"Elimina tabella {{tableName}}\",\n    edit_type: \"{{extra}} Modifica tipo {{typeName}}\",\n    delete_type: \"Elimina tipo {{typeName}}\",\n    add_relationship: \"Aggiungi relazione\",\n    edit_relationship: \"{{extra}} Modifica relazione {{refName}}\",\n    delete_relationship: \"Elimina relazione {{refName}}\",\n    not_found: \"Nessun risultato\",\n    pick_db: \"Scegli il database\",\n    generic: \"Generico\",\n    generic_description:\n      \"I diagrammi generici possono essere esportati in qualsiasi formato SQL, ma supportano un numero limitato di tipi di dati.\",\n    enums: \"Enums\",\n    add_enum: \"Aggiungi enum\",\n    edit_enum: \"{{extra}} Modifica enum {{enumName}}\",\n    delete_enum: \"Elimina enum\",\n    enum_w_no_name: \"Trovato enum senza nome\",\n    enum_w_no_values: \"Trovato enum '{{enumName}}' senza alcun valore\",\n    duplicate_enums: \"Enum duplicato con il nome '{{enumName}}'\",\n    no_enums: \"Nessun enum\",\n    no_enums_text: \"Definisci qui gli enum\",\n    declare_array: \"Dichiara array\",\n    empty_index_name: \"Dichiarato un indice senza nome nella tabella '{{tableName}}'\",\n    didnt_find_diagram: \"Ops! Impossibile trovare il diagramma.\",\n    unsigned: \"Senza segno\",\n    share: \"Condividi\",\n    unshare: \"Annulla condivisione\",\n    copy_link: \"Copia link\",\n    readme: \"README\",\n    failed_to_load: \"Caricamento non riuscito. Assicurati che il link sia corretto\",\n    share_info:\n      \"* La condivisione di questo link non consentirà di creare una sessione di collaborazione in tempo reale.\",\n    show_relationship_labels: \"Mostra le etichette di relazione\",\n    docs: \"Documentazione\",\n    supported_types: \"Tipi di file supportati:\",\n    bulk_update: \"Aggiornamento in blocco\",\n    multiselect: \"Multiselettore\",\n    export_saved_data: \"Esporta i dati salvati\",\n    dbml_view: \"Vista DBML\",\n    tab_view: \"Vista tabella\",\n  },\n};\n\nexport { it, italian };\n"
  },
  {
    "path": "src/i18n/locales/jp.js",
    "content": "const japanese = {\n  name: \"Japanese\",\n  native_name: \"Japanese\",\n  code: \"jp\",\n};\n\nconst jp = {\n  translation: {\n    report_bug: \"バグを報告\",\n    import_from: \"インポート\",\n    import: \"インポート\",\n    file: \"ファイル\",\n    new: \"新規\",\n    new_window: \"新しいウィンドウ\",\n    open: \"開く\",\n    save: \"保存\",\n    save_as: \"名前を付けて保存\",\n    save_as_template: \"テンプレートとして保存\",\n    template_saved: \"テンプレートが保存されました！\",\n    rename: \"名前を変更\",\n    delete_diagram: \"ダイアグラムを削除\",\n    are_you_sure_delete_diagram:\n      \"このダイアグラムを削除してもよろしいですか？ この操作は取り消せません。\",\n    oops_smth_went_wrong: \"おっと！何かがうまくいかなかった。\",\n    import_diagram: \"ダイアグラムをインポート\",\n    import_from_source: \"SQLからインポート\",\n    export_as: \"としてエクスポート\",\n    export_source: \"SQLをエクスポート\",\n    models: \"モデル\",\n    exit: \"終了\",\n    edit: \"編集\",\n    undo: \"元に戻す\",\n    redo: \"やり直す\",\n    clear: \"クリア\",\n    are_you_sure_clear:\n      \"ダイアグラムをクリアしてもよろしいですか？ この操作は取り消せません。\",\n    cut: \"切り取り\",\n    copy: \"コピー\",\n    paste: \"貼り付け\",\n    duplicate: \"複製\",\n    delete: \"削除\",\n    copy_as_image: \"画像としてコピー\",\n    view: \"表示\",\n    header: \"メニューバー\",\n    sidebar: \"サイドバー\",\n    issues: \"問題\",\n    presentation_mode: \"プレゼンテーションモード\",\n    strict_mode: \"厳格モード\",\n    field_details: \"フィールドの詳細\",\n    reset_view: \"ビューをリセット\",\n    show_grid: \"グリッドを表示\",\n    show_cardinality: \"カーディナリティを表示\",\n    theme: \"テーマ\",\n    light: \"ライト\",\n    dark: \"ダーク\",\n    zoom_in: \"ズームイン\",\n    zoom_out: \"ズームアウト\",\n    fullscreen: \"全画面表示\",\n    settings: \"設定\",\n    show_timeline: \"タイムラインを表示\",\n    autosave: \"自動保存\",\n    panning: \"パンニング\",\n    show_debug_coordinates: \"デバッグ座標を表示\",\n    transform: \"変換\",\n    viewbox: \"ビュー・ボックス\",\n    cursor_coordinates: \"カーソルの座標\",\n    coordinate_space: \"空間\",\n    coordinate_space_screen: \"スクリーン\",\n    coordinate_space_diagram: \"ダイアグラム\",\n    table_width: \"テーブル幅\",\n    language: \"言語\",\n    flush_storage: \"ストレージを消去\",\n    are_you_sure_flush_storage:\n      \"ストレージを消去してもよろしいですか？ これにより、すべてのダイアグラムとカスタムテンプレートが取り消し不能に削除されます。\",\n    storage_flushed: \"ストレージが消去されました\",\n    help: \"ヘルプ\",\n    shortcuts: \"ショートカット\",\n    ask_on_discord: \"Discordで質問する\",\n    feedback: \"フィードバック\",\n    no_changes: \"変更なし\",\n    loading: \"読み込み中...\",\n    last_saved: \"最後の保存\",\n    saving: \"保存中...\",\n    failed_to_save: \"保存に失敗しました\",\n    fit_window_reset: \"ウィンドウに合わせる / リセット\",\n    zoom: \"ズーム\",\n    add_table: \"テーブルを追加\",\n    add_area: \"エリアを追加\",\n    add_note: \"ノートを追加\",\n    add_type: \"タイプを追加\",\n    to_do: \"やるべきこと\",\n    tables: \"テーブル\",\n    relationships: \"リレーションシップ\",\n    subject_areas: \"主題領域\",\n    notes: \"ノート\",\n    types: \"タイプ\",\n    search: \"検索...\",\n    no_tables: \"テーブルがありません\",\n    no_tables_text: \"ダイアグラムの作成を開始しましょう！\",\n    no_relationships: \"リレーションシップがありません\",\n    no_relationships_text: \"フィールドを接続してリレーションシップを作成！\",\n    no_subject_areas: \"主題領域がありません\",\n    no_subject_areas_text: \"主題領域を追加してテーブルをグループ化しましょう！\",\n    no_notes: \"ノートがありません\",\n    no_notes_text: \"追加情報の記録にノートを使用\",\n    no_types: \"タイプがありません\",\n    no_types_text: \"カスタムデータタイプを作成\",\n    no_issues: \"問題は検出されていません。\",\n    strict_mode_is_on_no_issues:\n      \"厳格モードがオフになっているため、問題は表示されません。\",\n    name: \"名前\",\n    type: \"タイプ\",\n    null: \"Null\",\n    not_null: \"Not null\",\n    primary: \"主キー\",\n    unique: \"ユニーク\",\n    autoincrement: \"オートインクリメント\",\n    default_value: \"デフォルト\",\n    check: \"チェック式\",\n    this_will_appear_as_is:\n      \"*これが生成されたスクリプトにそのまま表示されます。\",\n    comment: \"コメント\",\n    add_field: \"フィールドを追加\",\n    values: \"値\",\n    size: \"サイズ\",\n    precision: \"精度\",\n    set_precision: \"精度を設定: 'サイズ, 桁数'\",\n    use_for_batch_input: \"バッチ入力に使用する場合は , を使用\",\n    indices: \"インデックス\",\n    add_index: \"インデックスを追加\",\n    select_fields: \"フィールドを選択\",\n    title: \"タイトル\",\n    not_set: \"設定されていません\",\n    foreign: \"外部キー\",\n    cardinality: \"カーディナリティ\",\n    on_update: \"更新時\",\n    on_delete: \"削除時\",\n    swap: \"入れ替え\",\n    one_to_one: \"1対1\",\n    one_to_many: \"1対多\",\n    many_to_one: \"多対1\",\n    content: \"内容\",\n    types_info:\n      \"この機能はPostgreSQLのようなオブジェクトリレーショナルDBMS向けです。\\nMySQLやMariaDBで使用した場合、対応するjsonの検証チェックと共にJSONタイプが生成されます。\\nSQLiteで使用した場合、BLOBに変換されます。\\nMSSQLで使用した場合、最初のフィールドへのタイプエイリアスが生成されます。\",\n    table_deleted: \"テーブルが削除されました\",\n    area_deleted: \"エリアが削除されました\",\n    note_deleted: \"ノートが削除されました\",\n    relationship_deleted: \"リレーションシップが削除されました\",\n    type_deleted: \"タイプが削除されました\",\n    cannot_connect: \"接続できません、列のタイプが異なります\",\n    copied_to_clipboard: \"クリップボードにコピーされました\",\n    create_new_diagram: \"新しいダイアグラムを作成\",\n    cancel: \"キャンセル\",\n    open_diagram: \"ダイアグラムを開く\",\n    rename_diagram: \"ダイアグラムの名前を変更\",\n    export: \"エクスポート\",\n    export_image: \"画像をエクスポート\",\n    create: \"作成\",\n    confirm: \"確認\",\n    last_modified: \"最終更新\",\n    drag_and_drop_files:\n      \"ファイルをここにドラッグ＆ドロップするかクリックしてアップロードします。\",\n    upload_sql_to_generate_diagrams:\n      \"SQLファイルをアップロードしてテーブルと列を自動生成します。\",\n    overwrite_existing_diagram: \"既存のダイアグラムを上書きする\",\n    only_mysql_supported:\n      \"*現在のところMySQLスクリプトの読み込みのみサポートされています。\",\n    blank: \"空白\",\n    filename: \"ファイル名\",\n    table_w_no_name: \"名前のないテーブルが宣言されました\",\n    duplicate_table_by_name: \"名前 '{{tableName}}' のテーブルが重複しています\",\n    empty_field_name: \"テーブル '{{tableName}}' のフィールド `name` が空です\",\n    empty_field_type: \"テーブル '{{tableName}}' のフィールド `type` が空です\",\n    no_values_for_field:\n      \"テーブル '{{tableName}}' のフィールド '{{fieldName}}' はタイプ `{{type}}` ですが、値が指定されていません\",\n    default_doesnt_match_type:\n      \"テーブル '{{tableName}}' のフィールド '{{fieldName}}' のデフォルト値がタイプと一致しません\",\n    not_null_is_null:\n      \"テーブル '{{tableName}}' のフィールド '{{fieldName}}' はNOT NULLですが、デフォルトはNULLです\",\n    duplicate_fields:\n      \"テーブル '{{tableName}}' 内に名前 '{{fieldName}}' のフィールドが重複しています\",\n    duplicate_index:\n      \"テーブル '{{tableName}}' 内に名前 '{{indexName}}' のインデックスが重複しています\",\n    empty_index:\n      \"テーブル '{{tableName}}' のインデックスは列をインデックスしていません\",\n    no_primary_key: \"テーブル '{{tableName}}' に主キーがありません\",\n    type_with_no_name: \"名前のないタイプが宣言されました\",\n    duplicate_types: \"名前 '{{typeName}}' のタイプが重複しています\",\n    type_w_no_fields:\n      \"フィールドのない空のタイプ '{{typeName}}' が宣言されました\",\n    empty_type_field_name: \"タイプ '{{typeName}}' のフィールド `name` が空です\",\n    empty_type_field_type: \"タイプ '{{typeName}}' のフィールド `type` が空です\",\n    no_values_for_type_field:\n      \"タイプ '{{typeName}}' のフィールド '{{fieldName}}' はタイプ `{{type}}` ですが、値が指定されていません\",\n    duplicate_type_fields:\n      \"タイプ '{{typeName}}' 内に名前 '{{fieldName}}' のフィールドが重複しています\",\n    duplicate_reference: \"名前 '{{refName}}' の参照が重複しています\",\n    circular_dependency:\n      \"テーブル '{{refName}}' を含む循環依存が検出されました\",\n    timeline: \"タイムライン\",\n    priority: \"優先度\",\n    none: \"なし\",\n    low: \"低\",\n    medium: \"中\",\n    high: \"高\",\n    sort_by: \"並べ替え\",\n    my_order: \"マイオーダー\",\n    completed: \"完了\",\n    alphabetically: \"アルファベット順\",\n    add_task: \"タスクを追加\",\n    details: \"詳細\",\n    no_tasks: \"タスクはまだありません。\",\n    no_activity: \"アクティビティはまだありません。\",\n    move_element: \"{{name}} を {{coords}} に移動\",\n    edit_area: \"{{extra}} エリア {{areaName}} を編集\",\n    delete_area: \"エリア {{areaName}} を削除\",\n    edit_note: \"{{extra}} ノート {{noteTitle}} を編集\",\n    delete_note: \"ノート {{noteTitle}} を削除\",\n    edit_table: \"{{extra}} テーブル {{tableName}} を編集\",\n    delete_table: \"テーブル {{tableName}} を削除\",\n    edit_type: \"{{extra}} タイプ {{typeName}} を編集\",\n    delete_type: \"タイプ {{typeName}} を削除\",\n    add_relationship: \"リレーションシップを追加\",\n    edit_relationship: \"{{extra}} リレーションシップ {{refName}} を編集\",\n    delete_relationship: \"リレーションシップ {{refName}} を削除\",\n    not_found: \"見つかりません\",\n    pick_db: \"データベースを選択\",\n    generic: \"一般\",\n    generic_description:\n      \"一般的なダイアグラムは任意のSQL方言にエクスポートできますが、データタイプのサポートは限定的です。\",\n    enums: \"列挙型\",\n    add_enum: \"列挙型を追加\",\n    edit_enum: \"{{extra}} 列挙型 {{enumName}} を編集\",\n    delete_enum: \"列挙型を削除\",\n    enum_w_no_name: \"名前のない列挙型が見つかりました\",\n    enum_w_no_values: \"列挙型 '{{enumName}}' に値がありません\",\n    duplicate_enums: \"名前 '{{enumName}}' の列挙型が重複しています\",\n    no_enums: \"列挙型がありません\",\n    no_enums_text: \"ここで列挙型を定義\",\n    declare_array: \"配列を宣言\",\n    empty_index_name:\n      \"テーブル '{{tableName}}' 内で名前のないインデックスが宣言されました\",\n    didnt_find_diagram: \"おっと！ダイアグラムが見つかりませんでした。\",\n    unsigned: \"符号なし\",\n    share: \"共有\",\n    copy_link: \"リンクをコピー\",\n    readme: \"README\",\n    failed_to_load:\n      \"読み込みに失敗しました。リンクが正しいか確認してください。\",\n    share_info:\n      \"* このリンクを共有してもリアルタイムコラボレーションセッションは作成されません。\",\n  },\n};\n\nexport { jp, japanese };\n"
  },
  {
    "path": "src/i18n/locales/ka.js",
    "content": "const kannada = {\n  name: \"Kannada\",\n  native_name: \"ಕನ್ನಡ\",\n  code: \"ka\",\n};\n\nconst ka = {\n  translation: {\n    report_bug: \"ದೋಷವನ್ನು ವರದಿ ಮಾಡಿ\",\n    import: \"ಆಮದು\",\n    inherits: \"ಪಡೆಯುತ್ತದೆ\",\n    merging_column_w_inherited_definition:\n      \"ಆನುವಂಶಿಕ ವ್ಯಾಖ್ಯಾನದೊಂದಿಗೆ '{{tableName}}' ಕೋಷ್ಟಕದಲ್ಲಿನ '{{fieldName}}' ಲಂಬಸಾಲು ವಿಲೀನಗೊಳ್ಳಲಿದೆ\",\n    import_from: \"ಇಂದ ಆಮದು ಮಾಡಿ\",\n    file: \"ಫೈಲ್\",\n    new: \"ಹೊಸ\",\n    new_window: \"ಹೊಸ ವಿಂಡೋ\",\n    no_saved_diagrams: \"ಯಾವುದೇ ಉಳಿಸಿದ ಚಿತ್ರಗಳಿಲ್ಲ\",\n    open: \"ತೆರೆಯಿರಿ\",\n    open_recent: \"ಇತ್ತೀಚಿನದನ್ನು ತೆರೆಯಿರಿ\",\n    save: \"ಉಳಿಸಿ\",\n    save_as: \"ಹೀಗೆ ಉಳಿಸಿ\",\n    save_as_template: \"ಟೆಂಪ್ಲೇಟಾಗಿ ಉಳಿಸಿ\",\n    template_saved: \"ಟೆಂಪ್ಲೇಟ್ ಉಳಿಸಲಾಗಿದೆ!\",\n    rename: \"ಮರುಹೆಸರಿಸಿ\",\n    delete_diagram: \"ಚಿತ್ರವನ್ನು ಅಳಿಸಿ\",\n    are_you_sure_delete_diagram:\n      \"ನೀವು ಈ ಚಿತ್ರವನ್ನು ಅಳಿಸಲು ಖಚಿತವಾಗಿ ಬಯಸುತ್ತೀರಾ? ಈ ಕಾರ್ಯಾಚರಣೆ ಬದಲಾಯಿಸಲಾಗದು.\",\n    oops_smth_went_wrong: \"ಅಯ್ಯೋ! ಏನೋ ತಪ್ಪಾಗಿದೆ.\",\n    import_diagram: \"ಚಿತ್ರವನ್ನು ಆಮದು ಮಾಡಿ\",\n    import_from_source: \"SQL ನಿಂದ ಆಮದು ಮಾಡಿ\",\n    export_as: \"ಹೀಗೆ ರಫ್ತು ಮಾಡಿ\",\n    export_source: \"SQL ರಫ್ತು ಮಾಡಿ\",\n    models: \"ಮಾದರಿಗಳು\",\n    exit: \"ನಿರ್ಗಮಿಸಿ\",\n    edit: \"ತಿದ್ದು\",\n    undo: \"ರದ್ದುಗೊಳಿಸಿ\",\n    redo: \"ಮರುಮಾಡಿ\",\n    clear: \"ತೆರವುಗೊಳಿಸಿ\",\n    are_you_sure_clear:\n      \"ನೀವು ಚಿತ್ರವನ್ನು ತೆರವುಗೊಳಿಸಲು ಖಚಿತವಾಗಿ ಬಯಸುತ್ತೀರಾ? ಇದು ಬದಲಾಯಿಸಲಾಗದು.\",\n    cut: \"ಕತ್ತರಿಸಿ\",\n    copy: \"ನಕಲಿಸಿ\",\n    paste: \"ಅಂಟಿಸಿ\",\n    duplicate: \"ನಕಲು\",\n    delete: \"ಅಳಿಸಿ\",\n    copy_as_image: \"ಚಿತ್ರವಾಗಿ ನಕಲಿಸಿ\",\n    view: \"ವೀಕ್ಷಣೆ\",\n    header: \"ಮೆನುಬಾರ್\",\n    sidebar: \"ಸೈಡ್‌ಬಾರ್\",\n    issues: \"ಸಮಸ್ಯೆಗಳು\",\n    presentation_mode: \"ಪ್ರಸ್ತುತಿ ಮೋಡ್\",\n    strict_mode: \"ಸ್ಟ್ರಿಕ್ಟ್ ಮೋಡ್\",\n    field_details: \"ಕ್ಷೇತ್ರದ ವಿವರಗಳು\",\n    reset_view: \"ವೀಕ್ಷಣೆ ಮರುಹೊಂದಿಸಿ\",\n    show_grid: \"ಗ್ರಿಡ್ ತೋರಿಸಿ\",\n    snap_to_grid: \"ಗ್ರಿಡ್‌ಗೆ ಸ್ನ್ಯಾಪ್ ಮಾಡಿ\",\n    show_datatype: \"ಡೇಟಾ ಪ್ರಕಾರವನ್ನು ತೋರಿಸಿ\",\n    show_cardinality: \"ಕಾರ್ಡಿನಾಲಿಟಿ ತೋರಿಸಿ\",\n    theme: \"ಥೀಮ್\",\n    light: \"ಬೆಳಕು\",\n    dark: \"ಕತ್ತಲೆ\",\n    zoom_in: \"ಜೂಮ್ ಇನ್\",\n    zoom_out: \"ಜೂಮ್ ಔಟ್\",\n    fullscreen: \"ಪೂರ್ಣ ಪರದೆ\",\n    settings: \"ಸೆಟ್ಟಿಂಗ್ಗಳು\",\n    show_timeline: \"ಟೈಮ್‌ಲೈನ್ ತೋರಿಸಿ\",\n    autosave: \"ಸ್ವಯಂ ಉಳಿಸಿ\",\n    panning: \"ಪ್ಯಾನಿಂಗ್\",\n    show_debug_coordinates: \"ಡಿಬಗ್ ಸಂಯೋಜನೆಗಳನ್ನು ತೋರಿಸಿ\",\n    transform: \"ಪರಿವರ್ತನೆ\",\n    viewbox: \"ವೀಕ್ಷಣಾ ಪೆಟ್ಟಿಗೆ\",\n    cursor_coordinates: \"ಕರ್ಸರ್ ಸಂಯೋಜನೆಗಳು\",\n    coordinate_space: \"ಅಂತರ\",\n    coordinate_space_screen: \"ಪರದೆ\",\n    coordinate_space_diagram: \"ಚಿತ್ರ\",\n    table_width: \"ಕೋಷ್ಟಕದ ಅಗಲ\",\n    language: \"ಭಾಷೆ\",\n    flush_storage: \"ಸಂಗ್ರಹವನ್ನು ಫ್ಲಷ್ ಮಾಡಿ\",\n    are_you_sure_flush_storage:\n      \"ನೀವು ಸಂಗ್ರಹವನ್ನು ಫ್ಲಷ್ ಮಾಡಲು ಖಚಿತವಾಗಿ ಬಯಸುತ್ತೀರಾ? ಇದು ನಿಮ್ಮ ಎಲ್ಲಾ ಚಿತ್ರಗಳು ಮತ್ತು ಕಸ್ಟಮ್ ಟೆಂಪ್ಲೇಟ್ಗಳನ್ನು ಬದಲಾಯಿಸಲಾಗದಂತೆ ಅಳಿಸುತ್ತದೆ.\",\n    storage_flushed: \"ಸಂಗ್ರಹವನ್ನು ಫ್ಲಷ್ ಮಾಡಲಾಗಿದೆ\",\n    help: \"ಸಹಾಯ\",\n    shortcuts: \"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು\",\n    ask_on_discord: \"Discord ನಲ್ಲಿ ಕೇಳಿ\",\n    feedback: \"ಪ್ರತಿಕ್ರಿಯೆ\",\n    no_changes: \"ಯಾವುದೇ ಬದಲಾವಣೆಗಳಿಲ್ಲ\",\n    loading: \"ಲೋಡ್ ಆಗುತ್ತಿದೆ...\",\n    last_saved: \"ಕೊನೆಯದಾಗಿ ಉಳಿಸಲಾಗಿದೆ\",\n    saving: \"ಉಳಿಸುತ್ತಿದೆ...\",\n    failed_to_save: \"ಉಳಿಸಲು ವಿಫಲವಾಗಿದೆ\",\n    fit_window_reset: \"ವಿಂಡೋಗೆ ಹೊಂದಿಸಿ / ಮರುಹೊಂದಿಸಿ\",\n    zoom: \"ಜೂಮ್\",\n    add_table: \"ಕೋಷ್ಟಕವನ್ನು ಸೇರಿಸಿ\",\n    add_area: \"ಪ್ರದೇಶವನ್ನು ಸೇರಿಸಿ\",\n    add_note: \"ಟಿಪ್ಪಣಿಯನ್ನು ಸೇರಿಸಿ\",\n    add_type: \"ಪ್ರಕಾರವನ್ನು ಸೇರಿಸಿ\",\n    to_do: \"ಮಾಡಬೇಕಾದವು\",\n    tables: \"ಕೋಷ್ಟಕಗಳು\",\n    relationships: \"ಸಂಬಂಧಗಳು\",\n    subject_areas: \"ವಿಷಯ ಪ್ರದೇಶಗಳು\",\n    notes: \"ಟಿಪ್ಪಣಿಗಳು\",\n    types: \"ಪ್ರಕಾರಗಳು\",\n    search: \"ಹುಡುಕಿ...\",\n    no_tables: \"ಯಾವುದೇ ಕೋಷ್ಟಕಗಳಿಲ್ಲ\",\n    no_tables_text: \"ನಿಮ್ಮ ಚಿತ್ರವನ್ನು ನಿರ್ಮಿಸಲು ಪ್ರಾರಂಭಿಸಿ!\",\n    no_relationships: \"ಯಾವುದೇ ಸಂಬಂಧಗಳಿಲ್ಲ\",\n    no_relationships_text:\n      \"ಕ್ಷೇತ್ರಗಳನ್ನು ಸಂಪರ್ಕಿಸಲು ಎಳೆಯಿರಿ ಮತ್ತು ಸಂಬಂಧಗಳನ್ನು ರೂಪಿಸಿ!\",\n    no_subject_areas: \"ಯಾವುದೇ ವಿಷಯ ಪ್ರದೇಶಗಳಿಲ್ಲ\",\n    no_subject_areas_text: \"ಕೋಷ್ಟಕಗಳನ್ನು ಗುಂಪು ಮಾಡಲು ವಿಷಯ ಪ್ರದೇಶಗಳನ್ನು ಸೇರಿಸಿ!\",\n    no_notes: \"ಯಾವುದೇ ಟಿಪ್ಪಣಿಗಳಿಲ್ಲ\",\n    no_notes_text: \"ಹೆಚ್ಚಿನ ಮಾಹಿತಿಯನ್ನು ದಾಖಲಿಸಲು ಟಿಪ್ಪಣಿಗಳನ್ನು ಬಳಸಿ\",\n    no_types: \"ಯಾವುದೇ ಪ್ರಕಾರಗಳಿಲ್ಲ\",\n    no_types_text: \"ನಿಮ್ಮ ಸ್ವಂತ ಕಸ್ಟಮ್ ಡೇಟಾ ಪ್ರಕಾರಗಳನ್ನು ಮಾಡಿ\",\n    no_issues: \"ಯಾವುದೇ ಸಮಸ್ಯೆಗಳು ಪತ್ತೆಯಾಗಿಲ್ಲ.\",\n    strict_mode_is_on_no_issues:\n      \"ಸ್ಟ್ರಿಕ್ಟ್ ಮೋಡ್ ಆಫ್ ಆಗಿದೆ ಆದ್ದರಿಂದ ಯಾವುದೇ ಸಮಸ್ಯೆಗಳು ತೋರಿಸಲಾಗುವುದಿಲ್ಲ.\",\n    name: \"ಹೆಸರು\",\n    type: \"ಪ್ರಕಾರ\",\n    null: \"ನಲ್\",\n    not_null: \"ನಾಟ್ ನಲ್\",\n    nullable: \"ನಲ್ಲಬಲ್\",\n    primary: \"ಪ್ರಾಥಮಿಕ\",\n    unique: \"ಅನನ್ಯ\",\n    autoincrement: \"ಸ್ವಯಂ ಏರಿಕೆ\",\n    default_value: \"ಡೀಫಾಲ್ಟ್\",\n    check: \"ಚೆಕ್ ಎಕ್ಸ್‌ಪ್ರೆಶನ್\",\n    this_will_appear_as_is:\n      \"*ಇದು ತಯಾರಿಸಲಾದ ಸ್ಕ್ರಿಪ್ಟ್‌ನಲ್ಲಿ ಹಾಗೆಯೇ ಕಾಣಿಸುತ್ತದೆ.\",\n    comment: \"ಟಿಪ್ಪಣಿ\",\n    add_field: \"ಕ್ಷೇತ್ರವನ್ನು ಸೇರಿಸಿ\",\n    values: \"ಮೌಲ್ಯಗಳು\",\n    size: \"ಗಾತ್ರ\",\n    precision: \"ನಿಖರತೆ\",\n    set_precision: \"ನಿಖರತೆ ಹೊಂದಿಸಿ: 'ಗಾತ್ರ, ಅಂಕೆಗಳು'\",\n    use_for_batch_input: \"ಬ್ಯಾಚ್ ಇನ್‌ಪುಟ್‌ಗಾಗಿ , ಬಳಸಿ\",\n    indices: \"ಸೂಚಿಗಳು\",\n    add_index: \"ಸೂಚಿಯನ್ನು ಸೇರಿಸಿ\",\n    select_fields: \"ಕ್ಷೇತ್ರಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ\",\n    title: \"ಶೀರ್ಷಿಕೆ\",\n    not_set: \"ಹೊಂದಿಸಲಾಗಿಲ್ಲ\",\n    foreign: \"ಫಾರಿನ್\",\n    cardinality: \"ಕಾರ್ಡಿನಾಲಿಟಿ\",\n    on_update: \"ಅಪ್‌ಡೇಟ್ ಆದಾಗ\",\n    on_delete: \"ಅಳಿಸುವಾಗ\",\n    swap: \"ಅದಲುಬದಲು\",\n    one_to_one: \"ಒಂದರಿಂದ ಒಂದು\",\n    one_to_many: \"ಒಂದರಿಂದ ಅನೇಕ\",\n    many_to_one: \"ಅನೇಕರಿಂದ ಒಂದು\",\n    content: \"ವಿಷಯ\",\n    types_info:\n      \"ಈ ವೈಶಿಷ್ಟ್ಯವು PostgreSQL ನಂತಹ ವಸ್ತು-ಸಂಬಂಧಿತ DBMS ಗಾಗಿ ಉದ್ದೇಶಿಸಲಾಗಿದೆ.\\nMySQL ಅಥವಾ MariaDB ಗಾಗಿ ಬಳಸಿದರೆ, JSON ಪ್ರಕಾರವು ಸಂಬಂಧಿತ json ಮಾನ್ಯತೆ ಪರಿಶೀಲನೆಯೊಂದಿಗೆ ತಯಾರಿಸಲಾಗುತ್ತದೆ.\\nSQLite ಗಾಗಿ ಬಳಸಿದರೆ, ಇದು BLOB ಗೆ ಅನುವಾದಿಸಲಾಗುತ್ತದೆ.\\nMSSQL ಗಾಗಿ ಬಳಸಿದರೆ, ಮೊದಲ ಕ್ಷೇತ್ರಕ್ಕೆ ಪ್ರಕಾರ ಅಲಿಯಾಸ್ ತಯಾರಿಸಲಾಗುತ್ತದೆ.\",\n    table_deleted: \"ಕೋಷ್ಟಕ ಅಳಿಸಲಾಗಿದೆ\",\n    area_deleted: \"ಪ್ರದೇಶ ಅಳಿಸಲಾಗಿದೆ\",\n    note_deleted: \"ಟಿಪ್ಪಣಿ ಅಳಿಸಲಾಗಿದೆ\",\n    relationship_deleted: \"ಸಂಬಂಧ ಅಳಿಸಲಾಗಿದೆ\",\n    type_deleted: \"ಪ್ರಕಾರ ಅಳಿಸಲಾಗಿದೆ\",\n    cannot_connect: \"ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ, ಕಂಬಿಗಳು ವಿಭಿನ್ನ ಪ್ರಕಾರಗಳಿವೆ\",\n    copied_to_clipboard: \"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ನಕಲಿಸಲಾಗಿದೆ\",\n    create_new_diagram: \"ಹೊಸ ಚಿತ್ರವನ್ನು ರಚಿಸಿ\",\n    cancel: \"ರದ್ದುಮಾಡಿ\",\n    open_diagram: \"ಚಿತ್ರವನ್ನು ತೆರೆಯಿರಿ\",\n    rename_diagram: \"ಚಿತ್ರವನ್ನು ಮರುಹೆಸರಿಸಿ\",\n    export: \"ರಫ್ತು\",\n    export_image: \"ಚಿತ್ರವನ್ನು ರಫ್ತು ಮಾಡಿ\",\n    create: \"ರಚಿಸಿ\",\n    confirm: \"ದೃಢೀಕರಿಸಿ\",\n    last_modified: \"ಕೊನೆಯದಾಗಿ ಬದಲಾಯಿಸಲಾಗಿದೆ\",\n    drag_and_drop_files:\n      \"ಫೈಲ್ ಅನ್ನು ಇಲ್ಲಿ ಎಳೆಯಿರಿ ಅಥವಾ ಅಪ್‌ಲೋಡ್ ಮಾಡಲು ಕ್ಲಿಕ್ ಮಾಡಿ.\",\n    upload_sql_to_generate_diagrams:\n      \"ನಿಮ್ಮ ಕೋಷ್ಟಕಗಳು ಮತ್ತು ಕಂಬಿಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತಯಾರಿಸಲು sql ಫೈಲ್ ಅನ್ನು ಅಪ್‌ಲೋಡ್ ಮಾಡಿ.\",\n    overwrite_existing_diagram: \"ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಚಿತ್ರವನ್ನು ಮರುಬರೆಯಿರಿ\",\n    only_mysql_supported:\n      \"*ಈಗಾಗಲೇ MySQL ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳನ್ನು ಮಾತ್ರ ಲೋಡ್ ಮಾಡುವುದು ಬೆಂಬಲಿತವಾಗಿದೆ.\",\n    blank: \"ಖಾಲಿ\",\n    filename: \"ಫೈಲ್ ಹೆಸರು\",\n    table_w_no_name: \"ಹೆಸರಿಲ್ಲದ ಕೋಷ್ಟಕವನ್ನು ಘೋಷಿಸಲಾಗಿದೆ\",\n    duplicate_table_by_name: \"ಹೆಸರಿನ ಮೂಲಕ ನಕಲು ಕೋಷ್ಟಕ '{{tableName}}'\",\n    empty_field_name: \"ಕೋಷ್ಟಕ '{{tableName}}' ನಲ್ಲಿ ಖಾಲಿ ಕ್ಷೇತ್ರ `ಹೆಸರು`\",\n    empty_field_type: \"ಕೋಷ್ಟಕ '{{tableName}}' ನಲ್ಲಿ ಖಾಲಿ ಕ್ಷೇತ್ರ `ಪ್ರಕಾರ`\",\n    no_values_for_field:\n      \"'{{fieldName}}' ಕ್ಷೇತ್ರವು ಕೋಷ್ಟಕ '{{tableName}}' ನಲ್ಲಿ `{{type}}` ಪ್ರಕಾರವಾಗಿದೆ ಆದರೆ ಯಾವುದೇ ಮೌಲ್ಯಗಳನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಲಾಗಿಲ್ಲ\",\n    default_doesnt_match_type:\n      \"ಕೋಷ್ಟಕ '{{tableName}}' ನಲ್ಲಿ '{{fieldName}}' ಕ್ಷೇತ್ರದ ಪೂರ್ವನಿಯೋಜಿತ ಮೌಲ್ಯವು ಅದರ ಪ್ರಕಾರಕ್ಕೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ\",\n    not_null_is_null:\n      \"'{{fieldName}}' ಕ್ಷೇತ್ರವು ಕೋಷ್ಟಕ '{{tableName}}' ನಲ್ಲಿ NOT NULL ಆದರೆ ಪೂರ್ವನಿಯೋಜಿತ NULL ಹೊಂದಿದೆ\",\n    duplicate_fields:\n      \"ಕೋಷ್ಟಕ '{{tableName}}' ನಲ್ಲಿ ಹೆಸರಿನ ಮೂಲಕ ನಕಲು ಕೋಷ್ಟಕ ಕ್ಷೇತ್ರಗಳು '{{fieldName}}'\",\n    duplicate_index:\n      \"ಕೋಷ್ಟಕ '{{tableName}}' ನಲ್ಲಿ ಹೆಸರಿನ ಮೂಲಕ ನಕಲು ಸೂಚಿ '{{indexName}}'\",\n    empty_index:\n      \"ಕೋಷ್ಟಕ '{{tableName}}' ನಲ್ಲಿ ಸೂಚಿ ಯಾವುದೇ ಕಂಬಿಗಳನ್ನು ಸೂಚಿಸುತ್ತಿಲ್ಲ\",\n    no_primary_key: \"ಕೋಷ್ಟಕ '{{tableName}}' ನಲ್ಲಿ ಪ್ರಾಥಮಿಕ ಕೀ ಇಲ್ಲ\",\n    type_with_no_name: \"ಹೆಸರಿಲ್ಲದ ಪ್ರಕಾರವನ್ನು ಘೋಷಿಸಲಾಗಿದೆ\",\n    duplicate_types: \"ಹೆಸರಿನ ಮೂಲಕ ನಕಲು ಪ್ರಕಾರಗಳು '{{typeName}}'\",\n    type_w_no_fields:\n      \"ಕ್ಷೇತ್ರಗಳಿಲ್ಲದ ಖಾಲಿ ಪ್ರಕಾರ '{{typeName}}' ಅನ್ನು ಘೋಷಿಸಲಾಗಿದೆ\",\n    empty_type_field_name: \"ಪ್ರಕಾರ '{{typeName}}' ನಲ್ಲಿ ಖಾಲಿ ಕ್ಷೇತ್ರ `ಹೆಸರು`\",\n    empty_type_field_type: \"ಪ್ರಕಾರ '{{typeName}}' ನಲ್ಲಿ ಖಾಲಿ ಕ್ಷೇತ್ರ `ಪ್ರಕಾರ`\",\n    no_values_for_type_field:\n      \"'{{fieldName}}' ಕ್ಷೇತ್ರವು '{{typeName}}' ಪ್ರಕಾರದಲ್ಲಿ `{{type}}` ಪ್ರಕಾರವಾಗಿದೆ ಆದರೆ ಯಾವುದೇ ಮೌಲ್ಯಗಳನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಲಾಗಿಲ್ಲ\",\n    duplicate_type_fields:\n      \"ಪ್ರಕಾರ '{{typeName}}' ನಲ್ಲಿ ಹೆಸರಿನ ಮೂಲಕ ನಕಲು ಪ್ರಕಾರ ಕ್ಷೇತ್ರಗಳು '{{fieldName}}'\",\n    duplicate_reference: \"ಹೆಸರಿನ ಮೂಲಕ ನಕಲು ಉಲ್ಲೇಖ '{{refName}}'\",\n    circular_dependency: \"ಕೋಷ್ಟಕ '{{refName}}' ಅನ್ನು ಒಳಗೊಂಡ ವೃತ್ತಾಕಾರದ ಅವಲಂಬನೆ\",\n    timeline: \"ಟೈಮ್‌ಲೈನ್\",\n    priority: \"ಆದ್ಯತೆ\",\n    none: \"ಯಾವುದೂ ಇಲ್ಲ\",\n    low: \"ಕಡಿಮೆ\",\n    medium: \"ಮಧ್ಯಮ\",\n    high: \"ಉನ್ನತ\",\n    sort_by: \"ಇದರಿಂದ ವಿಂಗಡಿಸಿ\",\n    my_order: \"ನನ್ನ ಆದೇಶ\",\n    completed: \"ಪೂರ್ಣಗೊಂಡಿದೆ\",\n    alphabetically: \"ಅಕ್ಷರಮಾಲೆಯ ಕ್ರಮದಲ್ಲಿ\",\n    add_task: \"ಕಾರ್ಯವನ್ನು ಸೇರಿಸಿ\",\n    details: \"ವಿವರಗಳು\",\n    no_tasks: \"ನಿಮ್ಮ ಬಳಿ ಇನ್ನೂ ಯಾವುದೇ ಕಾರ್ಯಗಳಿಲ್ಲ.\",\n    no_activity: \"ನಿಮ್ಮ ಬಳಿ ಇನ್ನೂ ಯಾವುದೇ ಚಟುವಟಿಕೆಗಳಿಲ್ಲ.\",\n    move_element: \"{{name}} ಅನ್ನು {{coords}} ಗೆ ಸರಿಸಿ\",\n    edit_area: \"{{extra}} ಪ್ರದೇಶವನ್ನು ಸಂಪಾದಿಸಿ {{areaName}}\",\n    delete_area: \"ಪ್ರದೇಶವನ್ನು ಅಳಿಸಿ {{areaName}}\",\n    edit_note: \"{{extra}} ಟಿಪ್ಪಣಿಯನ್ನು ಸಂಪಾದಿಸಿ {{noteTitle}}\",\n    delete_note: \"ಟಿಪ್ಪಣಿಯನ್ನು ಅಳಿಸಿ {{noteTitle}}\",\n    edit_table: \"{{extra}} ಕೋಷ್ಟಕವನ್ನು ಸಂಪಾದಿಸಿ {{tableName}}\",\n    delete_table: \"ಕೋಷ್ಟಕವನ್ನು ಅಳಿಸಿ {{tableName}}\",\n    edit_type: \"{{extra}} ಪ್ರಕಾರವನ್ನು ಸಂಪಾದಿಸಿ {{typeName}}\",\n    delete_type: \"ಪ್ರಕಾರವನ್ನು ಅಳಿಸಿ {{typeName}}\",\n    add_relationship: \"ಸಂಬಂಧವನ್ನು ಸೇರಿಸಿ\",\n    edit_relationship: \"{{extra}} ಸಂಬಂಧವನ್ನು ಸಂಪಾದಿಸಿ {{refName}}\",\n    delete_relationship: \"ಸಂಬಂಧವನ್ನು ಅಳಿಸಿ {{refName}}\",\n    not_found: \"ಕಂಡುಬಂದಿಲ್ಲ\",\n    pick_db: \"ಡೇಟಾಬೇಸ್ ಆಯ್ಕೆಮಾಡಿ\",\n    generic: \"ಸಾಮಾನ್ಯ\",\n    generic_description:\n      \"ಸಾಮಾನ್ಯ ಚಿತ್ರಗಳನ್ನು ಯಾವುದೇ SQL ರುಚಿಗೆ ರಫ್ತು ಮಾಡಬಹುದು ಆದರೆ ಕೆಲವು ಡೇಟಾ ಪ್ರಕಾರಗಳನ್ನು ಮಾತ್ರ ಬೆಂಬಲಿಸುತ್ತದೆ.\",\n    enums: \"ಎನಮ್‌ಗಳು\",\n    add_enum: \"ಎನಮ್ ಅನ್ನು ಸೇರಿಸಿ\",\n    edit_enum: \"{{extra}} ಎನಮ್ ಅನ್ನು ಸಂಪಾದಿಸಿ {{enumName}}\",\n    delete_enum: \"ಎನಮ್ ಅನ್ನು ಅಳಿಸಿ\",\n    enum_w_no_name: \"ಹೆಸರಿಲ್ಲದ ಎನಮ್ ಕಂಡುಬಂದಿದೆ\",\n    enum_w_no_values: \"ಎನಮ್ '{{enumName}}' ನಲ್ಲಿ ಯಾವುದೇ ಮೌಲ್ಯಗಳಿಲ್ಲ\",\n    duplicate_enums: \"ಹೆಸರಿನ ಮೂಲಕ ನಕಲು ಎನಮ್‌ಗಳು '{{enumName}}'\",\n    enum_deleted: \"ಎನಮ್ ಅಳಿಸಲಾಗಿದೆ\",\n    no_enums: \"ಯಾವುದೇ ಎನಮ್‌ಗಳಿಲ್ಲ\",\n    no_enums_text: \"ಇಲ್ಲಿ ಎನಮ್‌ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಿ\",\n    declare_array: \"ಅರೆ ಅನ್ನು ಘೋಷಿಸಿ\",\n    empty_index_name:\n      \"ಕೋಷ್ಟಕ '{{tableName}}' ನಲ್ಲಿ ಹೆಸರಿಲ್ಲದ ಸೂಚಿಯನ್ನು ಘೋಷಿಸಲಾಗಿದೆ\",\n    didnt_find_diagram: \"ಅಯ್ಯೋ! ಚಿತ್ರವನ್ನು ಕಂಡುಹಿಡಿಯಲಿಲ್ಲ.\",\n    unsigned: \"ಅನ್‌ಸೈನ್ಡ್\",\n    share: \"ಹಂಚಿಕೊಳ್ಳಿ\",\n    unshare: \"ಹಂಚಿಕೆಯನ್ನು ರದ್ದುಗೊಳಿಸಿ\",\n    copy_link: \"ಲಿಂಕ್ ನಕಲಿಸಿ\",\n    readme: \"README\",\n    failed_to_load:\n      \"ಲೋಡ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ. ಲಿಂಕ್ ಸರಿಯಾಗಿದೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ.\",\n    share_info:\n      \"* ಈ ಲಿಂಕ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುವುದರಿಂದ ಲೈವ್ ರಿಯಲ್-ಟೈಮ್ ಸಹಯೋಗ ಸೆಷನ್ ರಚಿಸಲಾಗುವುದಿಲ್ಲ.\",\n    show_relationship_labels: \"ಸಂಬಂಧದ ಲೇಬಲ್‌ಗಳನ್ನು ತೋರಿಸಿ\",\n    docs: \"ದಾಖಲೆಗಳು\",\n    supported_types: \"ಬೆಂಬಲಿತ ಫೈಲ್ ಪ್ರಕಾರಗಳು:\",\n    bulk_update: \"ಬಲ್ಕ್ ಅಪ್‌ಡೇಟ್\",\n    multiselect: \"ಮಲ್ಟಿಸೆಲೆಕ್ಟ್\",\n    export_saved_data: \"ಉಳಿಸಿದ ಡೇಟಾವನ್ನು ರಫ್ತು ಮಾಡಿ\",\n    dbml_view: \"DBML ವೀಕ್ಷಣೆ\",\n    tab_view: \"ಟ್ಯಾಬ್ ವೀಕ್ಷಣೆ\",\n    label: \"ಲೇಬಲ್\",\n    many_side_label: \"ಅನೇಕ(n) ಬದಿಯ ಲೇಬಲ್\",\n    version: \"ಆವೃತ್ತಿ\",\n    versions: \"ಆವೃತ್ತಿಗಳು\",\n    no_saved_versions: \"ಯಾವುದೇ ಉಳಿಸಿದ ಆವೃತ್ತಿಗಳಿಲ್ಲ\",\n    record_version: \"ಆವೃತ್ತಿಯನ್ನು ದಾಖಲಿಸಿ\",\n    commited_at: \"ಸಲ್ಲಿಸಿದ ಸಮಯ\",\n    read_only: \"ಓದಲು ಮಾತ್ರ\",\n    continue: \"ಮುಂದುವರಿಸಿ\",\n    restore_version: \"ಆವೃತ್ತಿಯನ್ನು ಮರುಸ್ಥಾಪಿಸಿ\",\n    restore_warning: \"ಮತ್ತೊಂದು ಆವೃತ್ತಿಯನ್ನು ಲೋಡ್ ಮಾಡುವುದರಿಂದ ಯಾವುದೇ ಬದಲಾವಣೆಗಳನ್ನು ತಿದ್ದಿ ಬರೆಯಲಾಗುತ್ತದೆ.\",\n    return_to_current: \"ಚಿತ್ರಕ್ಕೆ ಹಿಂತಿರುಗಿ\",\n    no_changes_to_record: \"ದಾಖಲಿಸಲು ಯಾವುದೇ ಬದಲಾವಣೆಗಳಿಲ್ಲ\",\n    click_to_view: \"ವೀಕ್ಷಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ\",\n    load_more: \"ಇನ್ನಷ್ಟು ಲೋಡ್ ಮಾಡಿ\",\n    clear_cache: \"ಕ್ಯಾಶೆ ತೆರವುಗೊಳಿಸಿ\",\n    cache_cleared: \"ಕ್ಯಾಶೆ ತೆರವುಗೊಳಿಸಲಾಗಿದೆ\",\n    failed_to_record_version: \"ಆವೃತ್ತಿಯನ್ನು ದಾಖಲಿಸಲು ವಿಫಲವಾಗಿದೆ\",\n    failed_to_load_diagram: \"ಚಿತ್ರವನ್ನು ಲೋಡ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ\",\n    see_all: \"ಎಲ್ಲವನ್ನೂ ನೋಡಿ\",\n    insert_sql: \"SQL ಸೇರಿಸಿ\",\n    upload_file: \"ಫೈಲ್ ಅಪ್‌ಲೋಡ್ ಮಾಡಿ\",\n  },\n};\n\nexport { ka, kannada };\n"
  },
  {
    "path": "src/i18n/locales/ko.js",
    "content": "const korean = {\n  name: \"Korean\",\n  native_name: \"한국어\",\n  code: \"ko\",\n};\n\nconst ko = {\n  translation: {\n    report_bug: \"문제 보고\",\n    import_from: \"가져오기\",\n    import: \"가져오기\",\n    file: \"파일\",\n    new: \"새로 만들기\",\n    new_window: \"새 탭에서 열기\",\n    open: \"열기\",\n    save: \"저장\",\n    save_as: \"다른 이름으로 저장\",\n    save_as_template: \"템플릿으로 저장\",\n    template_saved: \"템플릿이 저장되었습니다!\",\n    rename: \"이름 변경\",\n    delete_diagram: \"다이어그램 삭제\",\n    are_you_sure_delete_diagram:\n      \"이 다이어그램을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.\",\n    oops_smth_went_wrong: \"이런! 문제가 발생했습니다.\",\n    import_diagram: \"다이어그램 가져오기\",\n    import_from_source: \"SQL에서 가져오기\",\n    export_as: \"내보내기\",\n    export_source: \"SQL로 내보내기\",\n    models: \"모델\",\n    exit: \"끝내기\",\n    edit: \"편집\",\n    undo: \"실행 취소\",\n    redo: \"다시 실행\",\n    clear: \"지우기\",\n    are_you_sure_clear:\n      \"이 다이어그램을 지우시겠습니까? 이 작업은 되돌릴 수 없습니다.\",\n    cut: \"잘라내기\",\n    copy: \"복사\",\n    paste: \"붙여넣기\",\n    duplicate: \"복제\",\n    delete: \"삭제\",\n    copy_as_image: \"이미지로 복사\",\n    view: \"보기\",\n    header: \"메뉴바\",\n    sidebar: \"사이드바\",\n    issues: \"이슈\",\n    presentation_mode: \"발표 모드\",\n    strict_mode: \"엄격 모드\",\n    field_details: \"필드 세부 사항\",\n    reset_view: \"보기 초기화\",\n    show_grid: \"그리드 보기\",\n    show_cardinality: \"관계 보기\",\n    theme: \"테마\",\n    light: \"라이트\",\n    dark: \"다크\",\n    zoom_in: \"확대\",\n    zoom_out: \"축소\",\n    fullscreen: \"전체 화면\",\n    settings: \"설정\",\n    show_timeline: \"타임라인 보기\",\n    autosave: \"자동 저장\",\n    panning: \"캔버스 드래그 이동\",\n    show_debug_coordinates: \"디버그 좌표 보기\",\n    transform: \"변환\",\n    viewbox: \"뷰 박스\",\n    cursor_coordinates: \"커서 좌표\",\n    coordinate_space: \"좌표 공간\",\n    coordinate_space_screen: \"화면\",\n    coordinate_space_diagram: \"다이어그램\",\n    table_width: \"테이블 너비\",\n    language: \"언어\",\n    flush_storage: \"저장소 비우기\",\n    are_you_sure_flush_storage:\n      \"저장소를 비우시겠습니까? 이 작업은 되돌릴 수 없으며 모든 다이어그램과 사용자 정의 템플릿이 삭제됩니다.\",\n    storage_flushed: \"저장소가 비워졌습니다\",\n    help: \"도움말\",\n    shortcuts: \"단축키\",\n    ask_on_discord: \"디스코드에서 문의하기\",\n    feedback: \"피드백\",\n    no_changes: \"변경 사항 없음\",\n    loading: \"로딩 중...\",\n    last_saved: \"마지막 저장\",\n    saving: \"저장 중...\",\n    failed_to_save: \"저장 실패\",\n    fit_window_reset: \"창 크기에 맞추기/초기화\",\n    zoom: \"화면 확대/축소\",\n    add_table: \"테이블 추가\",\n    add_area: \"영역 추가\",\n    add_note: \"노트 추가\",\n    add_type: \"유형 추가\",\n    to_do: \"할 일\",\n    tables: \"테이블\",\n    relationships: \"관계\",\n    subject_areas: \"주제 영역\",\n    notes: \"노트\",\n    types: \"유형\",\n    search: \"검색...\",\n    no_tables: \"테이블 없음\",\n    no_tables_text: \"다이어그램을 만드세요!\",\n    no_relationships: \"관계 없음\",\n    no_relationships_text: \"필드를 연결하여 관계를 만드세요!\",\n    no_subject_areas: \"주제 영역 없음\",\n    no_subject_areas_text: \"테이블을 그룹화할 주제 영역을 추가하세요!\",\n    no_notes: \"노트 없음\",\n    no_notes_text: \"노트를 추가하여 추가 정보를 기록하세요\",\n    no_types: \"유형 없음\",\n    no_types_text: \"사용자 정의 데이터 유형을 만드세요\",\n    no_issues: \"감지된 이슈가 없습니다.\",\n    strict_mode_is_on_no_issues:\n      \"엄격 모드가 꺼져 있어 이슈가 표시되지 않습니다.\",\n    name: \"이름\",\n    type: \"유형\",\n    null: \"널\",\n    not_null: \"널 아님\",\n    primary: \"기본 키\",\n    unique: \"고유\",\n    autoincrement: \"자동 증가\",\n    default_value: \"기본값\",\n    check: \"검사 식\",\n    this_will_appear_as_is: \"*이 내용은 생성된 스크립트에 그대로 표시됩니다.\",\n    comment: \"주석\",\n    add_field: \"필드 추가\",\n    values: \"값\",\n    size: \"크기\",\n    precision: \"정밀도\",\n    set_precision: \"정밀도 설정: (크기, 자릿수)\",\n    use_for_batch_input: \"배치 입력을 위해서 ,(쉼표)를 사용하세요\",\n    indices: \"인덱스\",\n    add_index: \"인덱스 추가\",\n    select_fields: \"필드 선택\",\n    title: \"제목\",\n    not_set: \"설정되지 않음\",\n    foreign: \"외래 키\",\n    cardinality: \"카디널리티\",\n    on_update: \"업데이트 시\",\n    on_delete: \"삭제 시\",\n    swap: \"교환\",\n    one_to_one: \"일 대 일\",\n    one_to_many: \"일 대 다\",\n    many_to_one: \"다 대 일\",\n    content: \"내용\",\n    types_info:\n      \"이 기능은 PostgreSQL과 같은 객체 관계형 데이터베이스 관리 시스템에 적합합니다.\\nMySQL 또는 MariaDB에서는 해당 JSON 검사를 포함한 JSON 유형으로 생성됩니다.\\nSQLite에서는 BLOB으로 변환됩니다.\\nMSSQL에서는 첫 번째 필드의 유형 별칭이 생성됩니다.\",\n    table_deleted: \"테이블이 삭제되었습니다\",\n    area_deleted: \"영역이 삭제되었습니다\",\n    note_deleted: \"노트가 삭제되었습니다\",\n    relationship_deleted: \"관계가 삭제되었습니다\",\n    type_deleted: \"유형이 삭제되었습니다\",\n    cannot_connect: \"연결할 수 없습니다, 열의 유형이 다릅니다\",\n    copied_to_clipboard: \"클립보드에 복사되었습니다\",\n    create_new_diagram: \"새 다이어그램 만들기\",\n    cancel: \"취소\",\n    open_diagram: \"다이어그램 열기\",\n    rename_diagram: \"다이어그램 이름 변경\",\n    export: \"내보내기\",\n    export_image: \"이미지로 내보내기\",\n    create: \"생성\",\n    confirm: \"확인\",\n    last_modified: \"마지막 수정\",\n    drag_and_drop_files: \"파일을 여기에 끌어다 놓거나 클릭하여 업로드하세요.\",\n    upload_sql_to_generate_diagrams:\n      \"SQL 파일을 업로드하여 테이블과 열을 자동 생성하세요.\",\n    overwrite_existing_diagram: \"기존 다이어그램 덮어쓰기\",\n    only_mysql_supported: \"현재는 MySQL 스크립트만 지원합니다.\",\n    blank: \"비어있음\",\n    filename: \"파일 이름\",\n    table_w_no_name: \"이름이 없는 테이블이 선언되었습니다\",\n    duplicate_table_by_name:\n      \"'{{tableName}}'라는 이름의 테이블이 중복 선언되었습니다\",\n    empty_field_name: \"'{{tableName}}' 테이블의 필드 'name'이 비어 있습니다\",\n    empty_field_type: \"'{{tableName}}' 테이블의 필드 'type'이 비어 있습니다\",\n    no_values_for_field:\n      \"'{{tableName}}' 테이블의 '{{fieldName}}' 필드 유형이 '{{type}}'이지만 값이 지정되지 않았습니다\",\n    default_doesnt_match_type:\n      \"'{{tableName}}' 테이블의 '{{fieldName}}' 필드 기본값이 유형과 일치하지 않습니다\",\n    not_null_is_null:\n      \"'{{tableName}}' 테이블의 '{{fieldName}}' 필드가 NOT NULL이지만 기본값이 NULL입니다\",\n    duplicate_fields:\n      \"'{{tableName}}' 테이블에서 '{{fieldName}}' 필드가 중복 선언되었습니다\",\n    duplicate_index:\n      \"'{{tableName}}' 테이블에서 '{{indexName}}' 인덱스가 중복 선언되었습니다\",\n    empty_index: \"'{{tableName}}' 테이블의 인덱스에 열이 지정되지 않았습니다\",\n    no_primary_key: \"'{{tableName}}' 테이블에 기본 키가 없습니다\",\n    type_with_no_name: \"이름이 없는 유형이 선언되었습니다\",\n    duplicate_types: \"'{{typeName}}'라는 이름의 유형이 중복 선언되었습니다\",\n    type_w_no_fields:\n      \"'{{typeName}}' 유형에 필드가 없는 빈 유형이 선언되었습니다\",\n    empty_type_field_name: \"'{{typeName}}' 유형의 필드 'name'이 비어 있습니다\",\n    empty_type_field_type: \"'{{typeName}}' 유형의 필드 'type'이 비어 있습니다\",\n    no_values_for_type_field:\n      \"'{{typeName}}' 유형의 '{{fieldName}}' 필드 유형이 '{{type}}'이지만 값이 지정되지 않았습니다\",\n    duplicate_type_fields:\n      \"'{{typeName}}' 사용자 정의 클래스에서 '{{fieldName}}' 필드가 중복 선언되었습니다\",\n    duplicate_reference: \"'{{refName}}'라는 이름의 참조가 중복 선언되었습니다\",\n    circular_dependency: \"'{{refName}}' 테이블을 포함한 순환 종속이 있습니다\",\n    timeline: \"타임라인\",\n    priority: \"우선 순위\",\n    none: \"없음\",\n    low: \"낮음\",\n    medium: \"중간\",\n    high: \"높음\",\n    sort_by: \"정렬 기준\",\n    my_order: \"내 정렬\",\n    completed: \"완료됨\",\n    alphabetically: \"알파벳 순\",\n    add_task: \"작업 추가\",\n    details: \"세부 사항\",\n    no_tasks: \"아직 작업이 없습니다.\",\n    no_activity: \"아직 활동이 없습니다.\",\n    move_element: \"{{name}}을(를) {{coords}}로 이동\",\n    edit_area: \"{{extra}} 영역 {{areaName}} 수정\",\n    delete_area: \"영역 {{areaName}} 삭제\",\n    edit_note: \"{{extra}} 노트 {{noteTitle}} 수정\",\n    delete_note: \"노트 {{noteTitle}} 삭제\",\n    edit_table: \"{{extra}} 테이블 {{tableName}} 수정\",\n    delete_table: \"테이블 {{tableName}} 삭제\",\n    edit_type: \"{{extra}} 유형 {{typeName}} 수정\",\n    delete_type: \"유형 {{typeName}} 삭제\",\n    add_relationship: \"관계 추가\",\n    edit_relationship: \"{{extra}} 관계 {{refName}} 수정\",\n    delete_relationship: \"관계 {{refName}} 삭제\",\n    not_found: \"찾을 수 없음\",\n    pick_db: \"데이터베이스 선택\",\n    generic: \"일반\",\n    generic_description:\n      \"일반 다이어그램은 모든 SQL 유형으로 내보낼 수 있지만 지원하는 데이터 유형이 적습니다.\",\n    enums: \"열거형\",\n    add_enum: \"열거형 추가\",\n    edit_enum: \"{{extra}} 열거형 {{enumName}} 수정\",\n    delete_enum: \"열거형 삭제\",\n    enum_w_no_name: \"이름 없는 열거형이 발견되었습니다\",\n    enum_w_no_values: \"'{{enumName}}' 열거형에 값이 없습니다\",\n    duplicate_enums: \"'{{enumName}}'라는 이름의 열거형이 중복되었습니다\",\n    no_enums: \"열거형 없음\",\n    no_enums_text: \"여기에 열거형을 정의하세요\",\n    declare_array: \"배열 선언\",\n    empty_index_name:\n      \"'{{tableName}}' 테이블에 이름 없는 인덱스가 선언되었습니다\",\n    didnt_find_diagram: \"이런! 다이어그램을 찾을 수 없습니다.\",\n    unsigned: \"부호 없음\",\n  },\n};\n\nexport { ko, korean };\n"
  },
  {
    "path": "src/i18n/locales/ml.js",
    "content": "const malayalam = {\n    name: \"Malayalam\",\n    native_name: \"മലയാളം\",\n    code: \"ml\",\n};\n\nconst ml = {\n    translation: {\n        report_bug: \"ബഗ് റിപ്പോർട്ട് ചെയ്യുക\",\n        import: \"ഇമ്പോർട്ട്\",\n        inherits: \"പാരമ്പര്യമായി ലഭിക്കുന്നു\",\n        merging_column_w_inherited_definition: \"'{{tableName}}' ടേബിളിലെ '{{fieldName}}' കോളം പാരമ്പര്യ നിർവ്വചനത്തോട് ലയിപ്പിക്കും\",\n        import_from: \"ഇവിടെ നിന്ന് ഇമ്പോർട്ട് ചെയ്യുക\",\n        file: \"ഫയൽ\",\n        new: \"പുതിയത്\",\n        new_window: \"പുതിയ വിൻഡോ\",\n        no_saved_diagrams: \"നിങ്ങൾക്ക് സേവ് ചെയ്ത ഡയഗ്രമുകൾ ഒന്നുമില്ല\",\n        open: \"തുറക്കുക\",\n        open_recent: \"അടുത്തിടെ തുറന്നവ\",\n        save: \"സേവ് ചെയ്യുക\",\n        save_as: \"വേറൊന്നായി സേവ് ചെയ്യുക\",\n        save_as_template: \"ടെംപ്ലേറ്റായി സേവ് ചെയ്യുക\",\n        template_saved: \"ടെംപ്ലേറ്റ് സേവ് ചെയ്തു!\",\n        rename: \"പുനർനാമകരണം ചെയ്യുക\",\n        delete_diagram: \"ഡയഗ്രം ഡിലീറ്റ് ചെയ്യുക\",\n        are_you_sure_delete_diagram: \"നിങ്ങൾക്ക് ഈ ഡയഗ്രം ഡിലീറ്റ് ചെയ്യണമെന്ന് ഉറപ്പാണോ? ഈ പ്രവർത്തനം തിരിച്ചുകൂട്ടൽ സാധ്യമല്ല.\",\n        oops_smth_went_wrong: \"അയ്യോ! എന്തോ പ്രശ്നമുണ്ടായി.\",\n        import_diagram: \"ഡയഗ്രം ഇമ്പോർട്ട് ചെയ്യുക\",\n        import_from_source: \"SQL-ൽ നിന്ന് ഇമ്പോർട്ട് ചെയ്യുക\",\n        export_as: \"എക്സ്പോർട്ട് ചെയ്യുക\",\n        export_source: \"SQL എക്സ്പോർട്ട് ചെയ്യുക\",\n        models: \"മോഡലുകൾ\",\n        exit: \"പുറത്ത് കടക്കുക\",\n        edit: \"എഡിറ്റ് ചെയ്യുക\",\n        undo: \"അൺഡു\",\n        redo: \"റീഡു\",\n        clear: \"മായ്ക്കുക\",\n        are_you_sure_clear: \"ഡയഗ്രം മായ്ക്കണമെന്ന് ഉറപ്പാണോ? ഇത് തിരിച്ചുകൂട്ടൽ സാധ്യമല്ല.\",\n        cut: \"കട്ട് ചെയ്യുക\",\n        copy: \"കോപ്പി\",\n        paste: \"പേസ്റ്റ്\",\n        duplicate: \"ഡുപ്ലിക്കേറ്റ്\",\n        delete: \"ഡിലീറ്റ്\",\n        copy_as_image: \"ഇമേജായി കോപ്പി ചെയ്യുക\",\n        view: \"കാഴ്ച\",\n        header: \"മെനുബാർ\",\n        sidebar: \"സൈഡ്ബാർ\",\n        issues: \"പ്രശ്നങ്ങൾ\",\n        presentation_mode: \"പ്രസന്റേഷൻ മോഡ്\",\n        strict_mode: \"കർശനമായ മോഡ്\",\n        field_details: \"ഫീൽഡ് വിശദാംശങ്ങൾ\",\n        reset_view: \"കാഴ്ച റീസെറ്റ് ചെയ്യുക\",\n        show_grid: \"ഗ്രിഡ് കാണിക്കുക\",\n        snap_to_grid: \"ഗ്രിഡിലേക്ക് സ്നാപ്പ് ചെയ്യുക\",\n        show_datatype: \"ഡാറ്റാടൈപ്പ് കാണിക്കുക\",\n        show_cardinality: \"കാർഡിനാലിറ്റി കാണിക്കുക\",\n        theme: \"തീം\",\n        light: \"ലൈറ്റ്\",\n        dark: \"ഡാർക്ക്\",\n        zoom_in: \"സൂം ഇൻ\",\n        zoom_out: \"സൂം ഔട്ട്\",\n        fullscreen: \"ഫുൾസ്ക്രീൻ\",\n        settings: \"സെറ്റിംഗുകൾ\",\n        show_timeline: \"ടൈംലൈൻ കാണിക്കുക\",\n        autosave: \"ഓട്ടോസേവ്\",\n        panning: \"പാനിംഗ്\",\n        show_debug_coordinates: \"ഡീബഗ് കോർഡിനേറ്റുകൾ കാണിക്കുക\",\n        transform: \"ട്രാൻസ്ഫോം\",\n        viewbox: \"വ്യൂ ബോക്സ്\",\n        cursor_coordinates: \"കഴ്‌സർ കോർഡിനേറ്റുകൾ\",\n        coordinate_space: \"സ്പേസ്\",\n        coordinate_space_screen: \"സ്ക്രീൻ\",\n        coordinate_space_diagram: \"ഡയഗ്രം\",\n        table_width: \"ടേബിൾ വീതി\",\n        language: \"ഭാഷ\",\n        flush_storage: \"സ്റ്റോറേജ് ഫ്ലഷ് ചെയ്യുക\",\n        are_you_sure_flush_storage: \"സ്റ്റോറേജ് ഫ്ലഷ് ചെയ്യണമെന്ന് ഉറപ്പാണോ? ഇത് നിങ്ങളുടെ എല്ലാ ഡയഗ്രമുകളും കസ്റ്റം ടെംപ്ലേറ്റുകളും ഇല്ലാതാക്കും.\",\n        storage_flushed: \"സ്റ്റോറേജ് ഫ്ലഷ് ചെയ്തു\",\n        help: \"സഹായം\",\n        shortcuts: \"ഷോർട്ട്കട്ടുകൾ\",\n        ask_on_discord: \"ഡിസ്കോർഡിൽ ഞങ്ങളോട് ചോദിക്കുക\",\n        feedback: \"ഫീഡ്ബാക്ക്\",\n        no_changes: \"മാറ്റങ്ങളൊന്നുമില്ല\",\n        loading: \"ലോഡിംഗ്...\",\n        last_saved: \"അവസാനം സേവ് ചെയ്തത്\",\n        saving: \"സേവ് ചെയ്യുന്നു...\",\n        failed_to_save: \"സേവ് ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു\",\n        fit_window_reset: \"വിൻഡോയ്ക്ക് അനുയോജ്യമാക്കുക / റീസെറ്റ്\",\n        zoom: \"സൂം\",\n        add_table: \"ടേബിൾ ചേർക്കുക\",\n        add_area: \"ഏരിയ ചേർക്കുക\",\n        add_note: \"നോട്ട് ചേർക്കുക\",\n        add_type: \"ടൈപ്പ് ചേർക്കുക\",\n        to_do: \"ചെയ്യേണ്ടവ\",\n        tables: \"ടേബിളുകൾ\",\n        relationships: \"ബന്ധങ്ങൾ\",\n        subject_areas: \"വിഷയ ഏരിയകൾ\",\n        notes: \"നോട്ടുകൾ\",\n        types: \"ടൈപ്പുകൾ\",\n        search: \"തിരയുക...\",\n        no_tables: \"ടേബിളുകളൊന്നുമില്ല\",\n        no_tables_text: \"നിങ്ങളുടെ ഡയഗ്രം നിർമ്മിക്കാൻ തുടങ്ങുക!\",\n        no_relationships: \"ബന്ധങ്ങളൊന്നുമില്ല\",\n        no_relationships_text: \"ഫീൽഡുകൾ കണക്റ്റ് ചെയ്യാനും ബന്ധങ്ങൾ രൂപപ്പെടുത്താനും വലിച്ചിടുക!\",\n        no_subject_areas: \"വിഷയ ഏരിയകളൊന്നുമില്ല\",\n        no_subject_areas_text: \"ടേബിളുകൾ ഗ്രൂപ്പ് ചെയ്യാൻ വിഷയ ഏരിയകൾ ചേർക്കുക!\",\n        no_notes: \"നോട്ടുകളൊന്നുമില്ല\",\n        no_notes_text: \"അധിക വിവരങ്ങൾ രേഖപ്പെടുത്താൻ നോട്ടുകൾ ഉപയോഗിക്കുക\",\n        no_types: \"ടൈപ്പുകളൊന്നുമില്ല\",\n        no_types_text: \"നിങ്ങളുടെ സ്വന്തം കസ്റ്റം ഡാറ്റാ ടൈപ്പുകൾ നിർമ്മിക്കുക\",\n        no_issues: \"യാതൊരു പ്രശ്നങ്ങളും കണ്ടെത്തിയില്ല.\",\n        strict_mode_is_on_no_issues: \"കർശനമായ മോഡ് ഓഫ് ആയതിനാൽ പ്രശ്നങ്ങൾ പ്രദർശിപ്പിക്കില്ല.\",\n        name: \"പേര്\",\n        type: \"ടൈപ്പ്\",\n        null: \"നൾ\",\n        not_null: \"നൾ അല്ല\",\n        nullable: \"നൾ ആകാവുന്ന\",\n        primary: \"പ്രൈമറി\",\n        unique: \"യൂണിക്\",\n        autoincrement: \"ഓട്ടോ ഇൻക്രിമെന്റ്\",\n        default_value: \"ഡിഫോൾട്\",\n        check: \"ചെക്ക് എക്സ്പ്രെഷൻ\",\n        this_will_appear_as_is: \"*ജനറേറ്റ് ചെയ്ത സ്ക്രിപ്റ്റിൽ ഇത് അതേപടി കാണപ്പെടും.\",\n        comment: \"കമന്റ്\",\n        add_field: \"ഫീൽഡ് ചേർക്കുക\",\n        values: \"വിലുകൾ\",\n        size: \"സൈസ്\",\n        precision: \"പ്രിസിഷൻ\",\n        set_precision: \"പ്രിസിഷൻ സെറ്റ് ചെയ്യുക: 'സൈസ്, അക്കങ്ങൾ'\",\n        use_for_batch_input: \"ബാച്ച് ഇൻപുട്ടിനായി , ഉപയോഗിക്കുക\",\n        indices: \"ഇൻഡിസസ്\",\n        add_index: \"ഇൻഡെക്സ് ചേർക്കുക\",\n        select_fields: \"ഫീൽഡുകൾ തിരഞ്ഞെടുക്കുക\",\n        title: \"ടൈറ്റിൽ\",\n        not_set: \"സെറ്റ് ചെയ്തിട്ടില്ല\",\n        foreign: \"ഫോറിൻ\",\n        cardinality: \"കാർഡിനാലിറ്റി\",\n        on_update: \"അപ്‌ഡേറ്റ് ചെയ്യുമ്പോൾ\",\n        on_delete: \"ഡിലീറ്റ് ചെയ്യുമ്പോൾ\",\n        swap: \"സ്വാപ്പ് ചെയ്യുക\",\n        one_to_one: \"ഒന്ന് തൊട്ട് ഒന്ന്\",\n        one_to_many: \"ഒന്ന് തൊട്ട് പലത്\",\n        many_to_one: \"പലത് തൊട്ട് ഒന്ന്\",\n        content: \"ഉള്ളടക്കം\",\n        types_info: \"ഈ ഫീച്ചർ PostgreSQL പോലുള്ള ഒബ്ജെക്റ്റ്-റിലേഷണൽ ഡിബിഎംഎസുകൾക്കായി ഉദ്ദേശിച്ചതാണ്.\\nMySQL അല്ലെങ്കിൽ MariaDB-യ്ക്കായി ഉപയോഗിക്കുകയാണെങ്കിൽ, അനുയോജ്യമായ JSON വാലിഡേഷൻ ചെക്ക് ഉള്ള ഒരു JSON ടൈപ്പ് ജനറേറ്റ് ചെയ്യപ്പെടും.\\nSQLite-നായി ഉപയോഗിക്കുകയാണെങ്കിൽ അത് ഒരു BLOB ആയി വിവർത്തനം ചെയ്യപ്പെടും.\\nMSSQL-നായി ഉപയോഗിക്കുകയാണെങ്കിൽ ആദ്യ ഫീൽഡിലേക്കുള്ള ഒരു ടൈപ്പ് അലിയാസ് ജനറേറ്റ് ചെയ്യപ്പെടും.\",\n        table_deleted: \"ടേബിൾ ഡിലീറ്റ് ചെയ്തു\",\n        area_deleted: \"ഏരിയ ഡിലീറ്റ് ചെയ്തു\",\n        note_deleted: \"നോട്ട് ഡിലീറ്റ് ചെയ്തു\",\n        relationship_deleted: \"ബന്ധം ഡിലീറ്റ് ചെയ്തു\",\n        type_deleted: \"ടൈപ്പ് ഡിലീറ്റ് ചെയ്തു\",\n        cannot_connect: \"കണക്റ്റ് ചെയ്യാനാവില്ല, കോളങ്ങൾക്ക് വ്യത്യസ്ത ടൈപ്പുകൾ ഉണ്ട്\",\n        copied_to_clipboard: \"ക്ലിപ്പ്ബോർഡിലേക്ക് കോപ്പി ചെയ്തു\",\n        create_new_diagram: \"പുതിയ ഡയഗ്രം സൃഷ്ടിക്കുക\",\n        cancel: \"ക്യാൻസൽ\",\n        open_diagram: \"ഡയഗ്രം തുറക്കുക\",\n        rename_diagram: \"ഡയഗ്രം പുനർനാമകരണം ചെയ്യുക\",\n        export: \"എക്സ്പോർട്ട്\",\n        export_image: \"ഇമേജ് എക്സ്പോർട്ട് ചെയ്യുക\",\n        create: \"സൃഷ്ടിക്കുക\",\n        confirm: \"സ്ഥിരീകരിക്കുക\",\n        last_modified: \"അവസാനം മോഡിഫൈ ചെയ്തത്\",\n        drag_and_drop_files: \"ഫയൽ ഇവിടെ വലിച്ചിടുക അല്ലെങ്കിൽ അപ്‌ലോഡ് ചെയ്യാൻ ക്ലിക്ക് ചെയ്യുക.\",\n        upload_sql_to_generate_diagrams: \"നിങ്ങളുടെ ടേബിളുകളും കോളങ്ങളും ഓട്ടോ ജനറേറ്റ് ചെയ്യാൻ ഒരു SQL ഫയൽ അപ്‌ലോഡ് ചെയ്യുക.\",\n        overwrite_existing_diagram: \"നിലവിലുള്ള ഡയഗ്രം ഓവർറൈറ്റ് ചെയ്യുക\",\n        only_mysql_supported: \"*ഇപ്പോൾ വേണ്ടത്ര MySQL സ്ക്രിപ്റ്റുകൾ മാത്രമേ ലോഡ് ചെയ്യാൻ സപ്പോർട്ട് ഉള്ളൂ.\",\n        blank: \"ശൂന്യം\",\n        filename: \"ഫയൽനാമം\",\n        table_w_no_name: \"പേരില്ലാതെ ഒരു ടേബിൾ ഡിക്ലെയർ ചെയ്തു\",\n        duplicate_table_by_name: \"'{{tableName}}' എന്ന പേരിൽ ഡുപ്ലിക്കേറ്റ് ടേബിൾ\",\n        empty_field_name: \"'{{tableName}}' ടേബിളിൽ ശൂന്യമായ ഫീൽഡ് `പേര്`\",\n        empty_field_type: \"'{{tableName}}' ടേബിളിൽ ശൂന്യമായ ഫീൽഡ് `ടൈപ്പ്`\",\n        no_values_for_field: \"'{{tableName}}' ടേബിളിലെ '{{fieldName}}' ഫീൽഡ് `{{type}}` ടൈപ്പ് ആണെങ്കിലും വിലകൾ നിർവചിച്ചിട്ടില്ല\",\n        default_doesnt_match_type: \"'{{tableName}}' ടേബിളിലെ '{{fieldName}}' ഫീൽഡിനുള്ള ഡിഫോൾട് വില അതിന്റെ ടൈപ്പുമായി പൊരുത്തപ്പെടുന്നില്ല\",\n        not_null_is_null: \"'{{tableName}}' ടേബിളിലെ '{{fieldName}}' ഫീൽഡ് NOT NULL ആണെങ്കിലും ഡിഫോൾട് NULL ആണ്\",\n        duplicate_fields: \"'{{tableName}}' ടേബിളിൽ '{{fieldName}}' എന്ന പേരിൽ ഡുപ്ലിക്കേറ്റ് ഫീൽഡുകൾ\",\n        duplicate_index: \"'{{tableName}}' ടേബിളിൽ '{{indexName}}' എന്ന പേരിൽ ഡുപ്ലിക്കേറ്റ് ഇൻഡെക്സ്\",\n        empty_index: \"'{{tableName}}' ടേബിളിലെ ഇൻഡെക്സ് യാതൊരു കോളങ്ങളെയും ഇൻഡെക്സ് ചെയ്യുന്നില്ല\",\n        no_primary_key: \"'{{tableName}}' ടേബിളിന് പ്രൈമറി കീ ഇല്ല\",\n        type_with_no_name: \"പേരില്ലാതെ ഒരു ടൈപ്പ് ഡിക്ലെയർ ചെയ്തു\",\n        duplicate_types: \"'{{typeName}}' എന്ന പേരിൽ ഡുപ്ലിക്കേറ്റ് ടൈപ്പുകൾ\",\n        type_w_no_fields: \"ഫീൽഡുകളില്ലാതെ ശൂന്യമായ ടൈപ്പ് '{{typeName}}' ഡിക്ലെയർ ചെയ്തു\",\n        empty_type_field_name: \"'{{typeName}}' ടൈപ്പിൽ ശൂന്യമായ ഫീൽഡ് `പേര്`\",\n        empty_type_field_type: \"'{{typeName}}' ടൈപ്പിൽ ശൂന്യമായ ഫീൽഡ് `ടൈപ്പ്`\",\n        no_values_for_type_field: \"'{{typeName}}' ടൈപ്പിലെ '{{fieldName}}' ഫീൽഡ് `{{type}}` ടൈപ്പ് ആണെങ്കിലും വിലകൾ നിർവചിച്ചിട്ടില്ല\",\n        duplicate_type_fields: \"'{{typeName}}' ടൈപ്പിൽ '{{fieldName}}' എന്ന പേരിൽ ഡുപ്ലിക്കേറ്റ് ഫീൽഡുകൾ\",\n        duplicate_reference: \"'{{refName}}' എന്ന പേരിൽ ഡുപ്ലിക്കേറ്റ് റഫറൻസ്\",\n        circular_dependency: \"'{{refName}}' ടേബിൾ ഉൾപ്പെടുന്ന സർക്കുലാർ ഡിപെൻഡൻസി\",\n        timeline: \"ടൈംലൈൻ\",\n        priority: \"പ്രാധാന്യം\",\n        none: \"ഒന്നുമില്ല\",\n        low: \"കുറഞ്ഞ\",\n        medium: \"ഇടത്തരം\",\n        high: \"ഉയർന്ന\",\n        sort_by: \"ഇത് പ്രകാരം സോർട്ട് ചെയ്യുക\",\n        my_order: \"എന്റെ ക്രമം\",\n        completed: \"പൂർത്തിയായി\",\n        alphabetically: \"അക്ഷരമാലാക്രമത്തിൽ\",\n        add_task: \"ടാസ്ക് ചേർക്കുക\",\n        details: \"വിശദാംശങ്ങൾ\",\n        no_tasks: \"നിങ്ങൾക്ക് ഇതുവരെ ടാസ്കുകളൊന്നുമില്ല.\",\n        no_activity: \"നിങ്ങൾക്ക് ഇതുവരെ ആക്ടിവിറ്റിയൊന്നുമില്ല.\",\n        move_element: \"{{name}} എന്നത് {{coords}} ലേക്ക് നീക്കുക\",\n        edit_area: \"{{extra}} ഏരിയ {{areaName}} എഡിറ്റ് ചെയ്യുക\",\n        delete_area: \"ഏരിയ {{areaName}} ഡിലീറ്റ് ചെയ്യുക\",\n        edit_note: \"{{extra}} നോട്ട് {{noteTitle}} എഡിറ്റ് ചെയ്യുക\",\n        delete_note: \"നോട്ട് {{noteTitle}} ഡിലീറ്റ് ചെയ്യുക\",\n        edit_table: \"{{extra}} ടേബിൾ {{tableName}} എഡിറ്റ് ചെയ്യുക\",\n        delete_table: \"ടേബിൾ {{tableName}} ഡിലീറ്റ് ചെയ്യുക\",\n        edit_type: \"{{extra}} ടൈപ്പ് {{typeName}} എഡിറ്റ് ചെയ്യുക\",\n        delete_type: \"ടൈപ്പ് {{typeName}} ഡിലീറ്റ് ചെയ്യുക\",\n        add_relationship: \"ബന്ധം ചേർക്കുക\",\n        edit_relationship: \"{{extra}} ബന്ധം {{refName}} എഡിറ്റ് ചെയ്യുക\",\n        delete_relationship: \"ബന്ധം {{refName}} ഡിലീറ്റ് ചെയ്യുക\",\n        not_found: \"കണ്ടെത്തിയില്ല\",\n        pick_db: \"ഒരു ഡാറ്റാബേസ് തിരഞ്ഞെടുക്കുക\",\n        generic: \"ജനറിക്\",\n        generic_description: \"ജനറിക് ഡയഗ്രമുകൾ ഏത് SQL ഫ്ലേവറിലേക്കും എക്സ്പോർട്ട് ചെയ്യാം, പക്ഷേ കുറച്ച് ഡാറ്റാ ടൈപ്പുകൾ മാത്രമേ സപ്പോർട്ട് ചെയ്യൂ.\",\n        enums: \"എനംസ്\",\n        add_enum: \"എനം ചേർക്കുക\",\n        edit_enum: \"{{extra}} എനം {{enumName}} എഡിറ്റ് ചെയ്യുക\",\n        delete_enum: \"എനം ഡിലീറ്റ് ചെയ്യുക\",\n        enum_w_no_name: \"പേരില്ലാത്ത എനം കണ്ടെത്തി\",\n        enum_w_no_values: \"'{{enumName}}' എനത്തിന് വിലകളില്ല\",\n        duplicate_enums: \"'{{enumName}}' എന്ന പേരിൽ ഡുപ്ലിക്കേറ്റ് എനംസ്\",\n        no_enums: \"എനംസ് ഒന്നുമില്ല\",\n        no_enums_text: \"എനംസ് ഇവിടെ നിർവ്വചിക്കുക\",\n        declare_array: \"അറേ ഡിക്ലെയർ ചെയ്യുക\",\n        empty_index_name: \"'{{tableName}}' ടേബിളിൽ പേരില്ലാത്ത ഇൻഡെക്സ് ഡിക്ലെയർ ചെയ്തു\",\n        didnt_find_diagram: \"അയ്യോ! ഡയഗ്രം കണ്ടെത്തിയില്ല.\",\n        unsigned: \"അൺസൈൻഡ്\",\n        share: \"ഷെയർ ചെയ്യുക\",\n        unshare: \"അൺഷെയർ ചെയ്യുക\",\n        copy_link: \"ലിങ്ക് കോപ്പി ചെയ്യുക\",\n        readme: \"റീഡ്മി\",\n        failed_to_load: \"ലോഡ് ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു. ലിങ്ക് ശരിയാണെന്ന് ഉറപ്പാക്കുക.\",\n        share_info: \"*ഈ ലിങ്ക് ഷെയർ ചെയ്യുന്നത് ലൈവ് റിയൽ-ടൈം കൊളാബറേഷൻ സെഷൻ സൃഷ്ടിക്കില്ല.\",\n        show_relationship_labels: \"ബന്ധ ലേബലുകൾ കാണിക്കുക\",\n        docs: \"ഡോക്സ്\",\n        supported_types: \"സപ്പോർട്ട് ചെയ്യുന്ന ഫയൽ ടൈപ്പുകൾ:\",\n        bulk_update: \"ബൾക്ക് അപ്‌ഡേറ്റ്\",\n        multiselect: \"മൾട്ടിസെലെക്ട്\",\n        export_saved_data: \"സേവ് ചെയ്ത ഡാറ്റ എക്സ്പോർട്ട് ചെയ്യുക\",\n        dbml_view: \"DBML വ്യൂ\",\n        tab_view: \"ടാബ് വ്യൂ\",\n        label: \"ലേബൽ\",\n        many_side_label: \"മനി(n) സൈഡ് ലേബൽ\",\n        version: \"വേർഷൻ\",\n        versions: \"വേർഷനുകൾ\",\n        no_saved_versions: \"സേവ് ചെയ്ത വേർഷനുകളൊന്നുമില്ല\",\n        record_version: \"വേർഷൻ റെക്കോർഡ് ചെയ്യുക\",\n        commited_at: \"കമിറ്റ് ചെയ്ത സമയം\",\n        read_only: \"വായിക്കാൻ മാത്രം\",\n        continue: \"തുടരുക\",\n        restore_version: \"വേർഷൻ റെസ്റ്റോർ ചെയ്യുക\",\n        restore_warning: \"മറ്റൊരു വേർഷൻ ലോഡ് ചെയ്യുന്നത് എന്തെങ്കിലും മാറ്റങ്ങൾ ഓവർറൈറ്റ് ചെയ്യും.\",\n        return_to_current: \"ഡയഗ്രത്തിലേക്ക് മടങ്ങുക\",\n        no_changes_to_record: \"റെക്കോർഡ് ചെയ്യാൻ മാറ്റങ്ങളൊന്നുമില്ല\",\n        click_to_view: \"കാണാൻ ക്ലിക്ക് ചെയ്യുക\",\n        load_more: \"കൂടുതൽ ലോഡ് ചെയ്യുക\",\n        clear_cache: \"കാഷെ മായ്ക്കുക\",\n        cache_cleared: \"കാഷെ മായ്ച്ചു\",\n        failed_to_record_version: \"വേർഷൻ റെക്കോർഡ് ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു\",\n        failed_to_load_diagram: \"ഡയഗ്രം ലോഡ് ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു\",\n        see_all: \"എല്ലാം കാണുക\",\n    },\n};\n\nexport { ml, malayalam };"
  },
  {
    "path": "src/i18n/locales/mn.js",
    "content": "const mongolian = {\n  name: \"Mongolian\",\n  native_name: \"Монгол\",\n  code: \"mn\",\n};\n\nconst mn = {\n  translation: {\n    report_bug: \"Алдаа мэдээлэх\",\n    import: \"Импорт\",\n    inherits: \"Өвлөн авна\",\n    merging_column_w_inherited_definition:\n      \"'{{tableName}}' хүснэгтийн '{{fieldName}}' талбарын өвлөгдсөн тодорхойлолт нэгтгэгдэнэ\",\n    import_from: \"Импорт эх сурвалжаас\",\n    file: \"Файл\",\n    new: \"Шинэ\",\n    new_window: \"Шинэ цонх\",\n    no_saved_diagrams: \"Танд хадгалсан диаграмм байхгүй\",\n    open: \"Нээх\",\n    open_recent: \"Сүүлд нээгдсэн\",\n    save: \"Хадгалах\",\n    save_as: \"Өөр нэрээр хадгалах\",\n    save_as_template: \"Загвар болгон хадгалах\",\n    template_saved: \"Загвар хадгалагдлаа!\",\n    rename: \"Нэр солих\",\n    delete_diagram: \"Диаграмм устгах\",\n    are_you_sure_delete_diagram:\n      \"Энэ диаграммыг устгахдаа итгэлтэй байна уу? Буцаах боломжгүй.\",\n    oops_smth_went_wrong: \"Өө! Ямар нэгэн алдаа гарлаа.\",\n    import_diagram: \"Диаграмм импортлох\",\n    import_from_source: \"SQL-ээс импортлох\",\n    export_as: \"Экспорт\",\n    export_source: \"SQL-ыг экспортлох\",\n    models: \"Загварууд\",\n    exit: \"Гарах\",\n    edit: \"Засах\",\n    undo: \"Буцах\",\n    redo: \"Дахин хийх\",\n    clear: \"Цэвэрлэх\",\n    are_you_sure_clear:\n      \"Диаграмм цэвэрлэх үү? Буцаах боломжгүй.\",\n    cut: \"Таслах\",\n    copy: \"Хуулах\",\n    paste: \"Наах\",\n    duplicate: \"Хуулбарлах\",\n    delete: \"Устгах\",\n    copy_as_image: \"Зураг болгон хуулбарлах\",\n    view: \"Харах\",\n    header: \"Толгой хэсэг\",\n    sidebar: \"Хажуу самбар\",\n    issues: \"Асуудлууд\",\n    presentation_mode: \"Танилцуулах горим\",\n    strict_mode: \"Хатуу горим\",\n    field_details: \"Талбарын дэлгэрэнгүй\",\n    reset_view: \"Харагдацыг анхны болгох\",\n    show_grid: \"Сүлжээ харах\",\n    snap_to_grid: \"Сүлжээнд тааруулах\",\n    show_datatype: \"Өгөгдлийн төрлийг харуулах\",\n    show_cardinality: \"Кардиналь харуулах\",\n    theme: \"Сэдэв\",\n    light: \"Гэрэл\",\n    dark: \"Харанхуй\",\n    zoom_in: \"Ойртуулах\",\n    zoom_out: \"Холдуулах\",\n    fullscreen: \"Дэлгэц дүүрэн\",\n    settings: \"Тохиргоо\",\n    show_timeline: \"Цагийн түүх харах\",\n    autosave: \"Автоматаар хадгалах\",\n    panning: \"Гулсах\",\n    show_debug_coordinates: \"Алдааны координат харуулах\",\n    transform: \"Өөрчлөлт\",\n    viewbox: \"Харах хүрээ\",\n    cursor_coordinates: \"Курсорын координат\",\n    coordinate_space: \"Координатын орон\",\n    coordinate_space_screen: \"Дэлгэц\",\n    coordinate_space_diagram: \"Диаграмм\",\n    table_width: \"Хүснэгтийн өргөн\",\n    language: \"Хэл\",\n    flush_storage: \"Хадгалалт цэвэрлэх\",\n    are_you_sure_flush_storage:\n      \"Хадгалалтын санг цэвэрлэх үү? Таны бүх диаграмм болон загварууд устах болно.\",\n    storage_flushed: \"Хадгалалт цэвэрлэгдлээ\",\n    help: \"Тусламж\",\n    shortcuts: \"Товчлол\",\n    ask_on_discord: \"Discord дээр асуух\",\n    feedback: \"Санал хүсэлт\",\n    no_changes: \"Өөрчлөлт алга\",\n    loading: \"Уншиж байна...\",\n    last_saved: \"Сүүлд хадгалсан\",\n    saving: \"Хадгалж байна...\",\n    failed_to_save: \"Хадгалахад алдаа гарлаа\",\n    fit_window_reset: \"Цонхонд тааруулах / Анхны байдал\",\n    zoom: \"Томруулах\",\n    add_table: \"Хүснэгт нэмэх\",\n    add_area: \"Бүс нэмэх\",\n    add_note: \"Тэмдэглэл нэмэх\",\n    add_type: \"Төрөл нэмэх\",\n    to_do: \"Хийх зүйл\",\n    tables: \"Хүснэгтүүд\",\n    relationships: \"Харилцаанууд\",\n    subject_areas: \"Сэдвийн хэсгүүд\",\n    notes: \"Тэмдэглэлүүд\",\n    types: \"Төрлүүд\",\n    search: \"Хайх...\",\n    no_tables: \"Хүснэгт алга\",\n    no_tables_text: \"Диаграмм үүсгэж эхлээрэй!\",\n    no_relationships: \"Харилцаа алга\",\n    no_relationships_text: \"Талбаруудыг холбон харилцаа үүсгэнэ үү!\",\n    no_subject_areas: \"Сэдвийн бүс алга\",\n    no_subject_areas_text: \"Хүснэгтүүдийг бүлэглэхийн тулд бүс нэмнэ үү!\",\n    no_notes: \"Тэмдэглэл алга\",\n    no_notes_text: \"Нэмэлт мэдээллээ тэмдэглэлд бичнэ үү!\",\n    no_types: \"Төрөл алга\",\n    no_types_text: \"Өөрийн өгөгдлийн төрлийг энд үүсгэнэ үү\",\n    no_issues: \"Асуудал илрээгүй.\",\n    strict_mode_is_on_no_issues:\n      \"Хатуу горим идэвхтэй байна. Асуудал харагдахгүй.\",\n    name: \"Нэр\",\n    type: \"Төрөл\",\n    null: \"NULL\",\n    not_null: \"NULL биш\",\n    nullable: \"NULL зөвшөөрнө\",\n    primary: \"Үндсэн түлхүүр\",\n    unique: \"Давтагдахгүй\",\n    autoincrement: \"Авто өсөх\",\n    default_value: \"Анхдагч утга\",\n    check: \"Шалгах илэрхийлэл\",\n    this_will_appear_as_is: \"*Энэ нь үүсгэх скриптэд яг хэвээр гарна.\",\n    comment: \"Тайлбар\",\n    add_field: \"Талбар нэмэх\",\n    values: \"Утгууд\",\n    size: \"Хэмжээ\",\n    precision: \"Нарийвчлал\",\n    set_precision: \"Нарийвчлал: 'хэмжээ, цифр'\",\n    use_for_batch_input: \"Бөөнөөр оруулахад ашиглах\",\n    indices: \"Индексүүд\",\n    add_index: \"Индекс нэмэх\",\n    select_fields: \"Талбар сонгох\",\n    title: \"Гарчиг\",\n    not_set: \"Тохируулагдаагүй\",\n    foreign: \"Гадаад\",\n    cardinality: \"Кардиналь\",\n    on_update: \"Шинэчлэхэд\",\n    on_delete: \"Устгахад\",\n    swap: \"Солих\",\n    one_to_one: \"Нэг-ээс-нэг\",\n    one_to_many: \"Нэг-ээс-олон\",\n    many_to_one: \"Олон-ээс-нэг\",\n    content: \"Агуулга\",\n    types_info:\n      \"Энэ функц нь PostgreSQL зэрэг объект-холбоост системд зориулагдсан.\\nMySQL/MariaDB-д JSON төрөл үүсгэнэ.\\nSQLite-д BLOB болно.\\nMSSQL-д эхний талбарын төрлөөр alias үүсгэнэ.\",\n    table_deleted: \"Хүснэгт устгагдлаа\",\n    area_deleted: \"Бүс устгагдлаа\",\n    note_deleted: \"Тэмдэглэл устгагдлаа\",\n    relationship_deleted: \"Харилцаа устгагдлаа\",\n    type_deleted: \"Төрөл устгагдлаа\",\n    cannot_connect: \"Холбож чадахгүй — талбарын төрлүүд өөр байна\",\n    copied_to_clipboard: \"Хуулбарлагдлаа\",\n    create_new_diagram: \"Шинэ диаграмм үүсгэх\",\n    cancel: \"Цуцлах\",\n    open_diagram: \"Диаграмм нээх\",\n    rename_diagram: \"Диаграммын нэр солих\",\n    export: \"Экспорт\",\n    export_image: \"Зураг экспортлох\",\n    create: \"Үүсгэх\",\n    confirm: \"Батлах\",\n    last_modified: \"Сүүлд өөрчлөгдсөн\",\n    drag_and_drop_files: \"Файлыг энд чирж оруулна уу, эсвэл дарж сонгоно уу.\",\n    upload_sql_to_generate_diagrams:\n      \"Хүснэгт болон талбаруудыг автоматаар үүсгэхийн тулд SQL файл оруулна уу.\",\n    overwrite_existing_diagram: \"Одоогийн диаграммыг дарж бичих\",\n    only_mysql_supported:\n      \"*Одоогоор зөвхөн MySQL скриптийн импорт дэмжигдэж байна.\",\n    blank: \"Хоосон\",\n    filename: \"Файлын нэр\",\n    table_w_no_name: \"Нэргүй хүснэгт тодорхойлогдсон\",\n    duplicate_table_by_name: \"Давхардсан хүснэгт: '{{tableName}}'\",\n    empty_field_name:\n      \"'{{tableName}}' хүснэгт дэх хоосон талбарын `name`\",\n    empty_field_type:\n      \"'{{tableName}}' хүснэгт дэх хоосон талбарын `type`\",\n    no_values_for_field:\n      \"'{{tableName}}' хүснэгтийн '{{fieldName}}' талбар `{{type}}` төрөлтэй боловч утга заагаагүй байна\",\n    default_doesnt_match_type:\n      \"'{{tableName}}' хүснэгтийн '{{fieldName}}' талбарын анхдагч утга төрөлтэй нь тохирохгүй\",\n    not_null_is_null:\n      \"'{{fieldName}}' талбар '{{tableName}}' дээр NOT NULL боловч анхдагч утга нь NULL байна\",\n    duplicate_fields:\n      \"'{{tableName}}' хүснэгтэд '{{fieldName}}' нэртэй давхар талбар байна\",\n    duplicate_index:\n      \"'{{tableName}}' хүснэгтэд '{{indexName}}' нэртэй давхар индекс байна\",\n    empty_index:\n      \"'{{tableName}}' хүснэгтийн индекс ямар ч багана сонгоогүй\",\n    no_primary_key:\n      \"'{{tableName}}' хүснэгтэд үндсэн түлхүүр алга\",\n    type_with_no_name: \"Нэргүй төрөл тодорхойлогдсон\",\n    duplicate_types: \"'{{typeName}}' нэртэй давхар төрөл\",\n    type_w_no_fields:\n      \"'{{typeName}}' төрөл талбаргүй хоосон байна\",\n    empty_type_field_name:\n      \"'{{typeName}}' төрөл дэх хоосон талбарын `name`\",\n    empty_type_field_type:\n      \"'{{typeName}}' төрөл дэх хоосон талбарын `type`\",\n    no_values_for_type_field:\n      \"'{{typeName}}' төрөл дэх '{{fieldName}}' талбар `{{type}}` боловч утга үгүй\",\n    duplicate_type_fields:\n      \"'{{typeName}}' төрөл дотор '{{fieldName}}' нэртэй давхар талбар\",\n    duplicate_reference: \"'{{refName}}' нэртэй давхар холбоос\",\n    circular_dependency:\n      \"'{{refName}}' хүснэгттэй холбоотой тойрог хамаарал илэрлээ\",\n    timeline: \"Цагийн шугам\",\n    priority: \"Тэргүүлэх байдал\",\n    none: \"Байхгүй\",\n    low: \"Бага\",\n    medium: \"Дунд\",\n    high: \"Өндөр\",\n    sort_by: \"Эрэмбэлэх\",\n    my_order: \"Миний эрэмбэ\",\n    completed: \"Гүйцэтгэсэн\",\n    alphabetically: \"Үсгийн дарааллаар\",\n    add_task: \"Даалгавар нэмэх\",\n    details: \"Дэлгэрэнгүй\",\n    no_tasks: \"Даалгавар алга.\",\n    no_activity: \"Үйл ажиллагаа алга.\",\n    move_element:\n      \"'{{name}}' элементийг '{{coords}}' руу шилжүүлэв\",\n    edit_area: \"Бүс засах {{areaName}} {{extra}}\",\n    delete_area: \"Бүс устгах {{areaName}}\",\n    edit_note: \"Тэмдэглэл засах {{noteTitle}} {{extra}}\",\n    delete_note: \"Тэмдэглэл устгах {{noteTitle}}\",\n    edit_table: \"Хүснэгт засах {{tableName}} {{extra}}\",\n    delete_table: \"Хүснэгт устгах {{tableName}}\",\n    edit_type: \"Төрөл засах {{typeName}} {{extra}}\",\n    delete_type: \"Төрөл устгах {{typeName}}\",\n    add_relationship: \"Харилцаа нэмэх\",\n    edit_relationship: \"Харилцаа засах {{refName}} {{extra}}\",\n    delete_relationship: \"Харилцаа устгах {{refName}}\",\n    not_found: \"Олдсонгүй\",\n    pick_db: \"Өгөгдлийн сан сонгох\",\n    generic: \"Ердийн\",\n    generic_description:\n      \"Ердийн диаграмм SQL бүх хэлбэрт экспортлогдох бололцоотой ч зарим өгөгдлийн төрлүүд хязгаарлагдмал.\",\n    enums: \"Enum-ууд\",\n    add_enum: \"Enum нэмэх\",\n    edit_enum: \"Enum засах {{enumName}} {{extra}}\",\n    delete_enum: \"Enum устгах\",\n    enum_w_no_name: \"Нэргүй enum илэрлээ\",\n    enum_w_no_values: \"'{{enumName}}' enum-д утга байхгүй\",\n    duplicate_enums: \"'{{enumName}}' нэртэй давхар enum\",\n    enum_deleted: \"Enum устгагдлаа\",\n    no_enums: \"Enum байхгүй\",\n    no_enums_text: \"Энд enum-уудыг тодорхойлно уу\",\n    declare_array: \"Массив зарлах\",\n    empty_index_name:\n      \"'{{tableName}}' хүснэгтэд нэргүй индекс тодорхойлогдсон\",\n    didnt_find_diagram: \"Өө! Диаграмм олдсонгүй.\",\n    unsigned: \"Тэмдэггүй\",\n    share: \"Хуваалцах\",\n    unshare: \"Хуваалцахыг цуцлах\",\n    copy_link: \"Холбоос хуулбарлах\",\n    readme: \"README\",\n    failed_to_load:\n      \"Ачаалахад алдаа гарлаа. Холбоос зөв эсэхийг шалгана уу.\",\n    share_info:\n      \"* Энэ холбоосыг хуваалцах нь бодит цагийн хамтын ажиллагаа биш.\",\n    show_relationship_labels:\n      \"Харилцааны шошго харуулах\",\n    docs: \"Баримт бичиг\",\n    supported_types: \"Дэмжигдэх файл төрлүүд:\",\n    bulk_update: \"Бөөн шинэчлэлт\",\n    multiselect: \"Олон сонголт\",\n    export_saved_data: \"Хадгалсан өгөгдлийг экспортлох\",\n    dbml_view: \"DBML харагдалт\",\n    tab_view: \"Tab харагдалт\",\n    label: \"Шошго\",\n    many_side_label: \"Олон талын шошго (n)\",\n    version: \"Хувилбар\",\n    versions: \"Хувилбарууд\",\n    no_saved_versions: \"Хадгалсан хувилбар алга\",\n    record_version: \"Хувилбар бүртгэх\",\n    commited_at: \"Коммит хийсэн огноо\",\n    read_only: \"Зөвхөн унших\",\n    continue: \"Үргэлжлүүлэх\",\n    restore_version: \"Хувилбар сэргээх\",\n    restore_warning:\n      \"Хувилбар ачаалбал одоогийн өөрчлөлтүүд дарж бичигдэнэ.\",\n    return_to_current: \"Одоогийн диаграмм руу буцах\",\n    no_changes_to_record: \"Бүртгэх өөрчлөлт алга\",\n    click_to_view: \"Харах бол дарна уу\",\n    load_more: \"Илүү ачаалах\",\n    clear_cache: \"Кэш цэвэрлэх\",\n    cache_cleared: \"Кэш цэвэрлэгдлээ\",\n    failed_to_record_version:\n      \"Хувилбар бүртгэхэд алдаа гарлаа\",\n    failed_to_load_diagram:\n      \"Диаграмм ачаалахад алдаа гарлаа\",\n    see_all: \"Бүгдийг харах\",\n    insert_sql: \"SQL оруулах\",\n    upload_file: \"Файл оруулах\",\n  },\n};\n\nexport { mn, mongolian };"
  },
  {
    "path": "src/i18n/locales/mr.js",
    "content": "const marathi = {\n  name: \"Marathi\",\n  native_name: \"मराठी\",\n  code: \"mr\",\n};\n\nconst mr = {\n  translation: {\n    report_bug: \"बग रिपोर्ट करा\",\n    import_from: \"आयात\",\n    import: \"आयात\",\n    file: \"फाइल\",\n    new: \"नवीन\",\n    new_window: \"नवीन विंडो\",\n    open: \"उघडा\",\n    open_recent: \"अलीकडील उघडा\",\n    no_saved_diagrams: \"आपल्याकडे कोणतेही जतन केलेले डायग्राम नाहीत\",\n    save: \"जतन\",\n    save_as: \"च्या रूपात जतन करा\",\n    save_as_template: \"टेम्पलेट म्हणून जतन करा\",\n    template_saved: \"टेम्पलेट जतन झाले!\",\n    rename: \"नाव बदला\",\n    delete_diagram: \"डायग्राम हटवा\",\n    are_you_sure_delete_diagram:\n      \"आपण खरोखर हा डायग्राम हटवू इच्छिता? ही क्रिया अपरिवर्तनीय आहे.\",\n    oops_smth_went_wrong: \"अरे! काहीतरी चूक झाली.\",\n    import_diagram: \"डायग्राम आयात करा\",\n    import_from_source: \"SQL मधून आयात करा\",\n    export_as: \"च्या रूपात निर्यात करा\",\n    export_source: \"SQL निर्यात करा\",\n    models: \"मॉडेल्स\",\n    exit: \"बाहेर पडा\",\n    edit: \"संपादन करा\",\n    undo: \"पूर्ववत करा\",\n    redo: \"पुन्हा करा\",\n    clear: \"साफ करा\",\n    are_you_sure_clear:\n      \"आपण खरोखर हा डायग्राम साफ करू इच्छिता? ही क्रिया अपरिवर्तनीय आहे.\",\n    cut: \"कापा\",\n    copy: \"कॉपी करा\",\n    paste: \"पेस्ट करा\",\n    duplicate: \"प्रतिलिपी बनवा\",\n    delete: \"हटवा\",\n    copy_as_image: \"प्रतिमेच्या रूपात कॉपी करा\",\n    view: \"दृश्य\",\n    header: \"मेनूबार\",\n    sidebar: \"साइडबार\",\n    issues: \"समस्या\",\n    presentation_mode: \"प्रस्तुतीकरण मोड\",\n    strict_mode: \"कडक मोड\",\n    field_details: \"फील्ड तपशील\",\n    reset_view: \"दृश्य रीसेट करा\",\n    show_grid: \"ग्रिड दाखवा\",\n    snap_to_grid: \"ग्रिडला स्नॅप करा\",\n    show_datatype: \"डेटाटाइप दाखवा\",\n    show_cardinality: \"कार्डिनॅलिटी दाखवा\",\n    theme: \"थीम\",\n    light: \"प्रकाश\",\n    dark: \"अंधार\",\n    zoom_in: \"झूम इन\",\n    zoom_out: \"झूम आऊट\",\n    fullscreen: \"पूर्ण स्क्रीन\",\n    settings: \"सेटिंग्स\",\n    show_timeline: \"टाइमलाइन दाखवा\",\n    autosave: \"ऑटोसेव\",\n    panning: \"पॅनिंग\",\n    show_debug_coordinates: \"डीबग निर्देशांक दाखवा\",\n    transform: \"रूपांतर\",\n    viewbox: \"व्ह्यू बॉक्स\",\n    cursor_coordinates: \"कर्सर निर्देशांक\",\n    coordinate_space: \"स्पेस\",\n    coordinate_space_screen: \"स्क्रीन\",\n    coordinate_space_diagram: \"डायग्राम\",\n    table_width: \"टेबलची रुंदी\",\n    language: \"भाषा\",\n    flush_storage: \"स्टोरेज साफ करा\",\n    are_you_sure_flush_storage:\n      \"आपण खरोखर स्टोरेज साफ करू इच्छिता? हे सर्व आपले डायग्राम आणि कस्टम टेम्पलेट्स अपरिवर्तनीयपणे हटवेल.\",\n    storage_flushed: \"स्टोरेज साफ केले\",\n    help: \"मदत\",\n    shortcuts: \"शॉर्टकट्स\",\n    ask_on_discord: \"आमच्याकडे Discord वर विचारा\",\n    feedback: \"प्रतिक्रिया\",\n    no_changes: \"कोणतेही बदल नाहीत\",\n    loading: \"लोड होत आहे...\",\n    last_saved: \"शेवटचा जतन\",\n    saving: \"जतन होत आहे...\",\n    failed_to_save: \"जतन करण्यात अयशस्वी\",\n    fit_window_reset: \"विंडो फिट करा / रीसेट करा\",\n    zoom: \"झूम\",\n    add_table: \"टेबल जोडा\",\n    add_area: \"क्षेत्र जोडा\",\n    add_note: \"नोंद जोडा\",\n    add_type: \"प्रकार जोडा\",\n    to_do: \"करण्यासाठी\",\n    tables: \"टेबल्स\",\n    relationships: \"संबंध\",\n    subject_areas: \"विषय क्षेत्रे\",\n    notes: \"नोंदी\",\n    types: \"प्रकार\",\n    search: \"शोधा...\",\n    no_tables: \"कोणतेही टेबल्स नाहीत\",\n    no_tables_text: \"आपला डायग्राम तयार करण्यास प्रारंभ करा!\",\n    no_relationships: \"कोणतेही संबंध नाहीत\",\n    no_relationships_text: \"फील्ड्स कनेक्ट करण्यासाठी खेचा आणि संबंध तयार करा!\",\n    no_subject_areas: \"कोणतेही विषय क्षेत्रे नाहीत\",\n    no_subject_areas_text: \"टेबल्स ग्रुप करण्यासाठी विषय क्षेत्रे जोडा!\",\n    no_notes: \"कोणतेही नोट्स नाहीत\",\n    no_notes_text: \"अतिरिक्त माहिती नोंदवण्यासाठी नोट्स वापरा\",\n    no_types: \"कोणतेही प्रकार नाहीत\",\n    no_types_text: \"आपले स्वतःचे कस्टम डेटा प्रकार तयार करा\",\n    no_issues: \"कोणत्याही समस्या आढळल्या नाहीत.\",\n    strict_mode_is_on_no_issues:\n      \"कडक मोड बंद आहे म्हणून कोणत्याही समस्या दाखवल्या जाणार नाहीत.\",\n    name: \"नाव\",\n    type: \"प्रकार\",\n    null: \"नल\",\n    not_null: \"नल नाही\",\n    primary: \"प्राथमिक\",\n    unique: \"युनिक\",\n    autoincrement: \"स्वतः वाढ\",\n    default_value: \"डिफ़ॉल्ट\",\n    check: \"तपासणी अभिव्यक्ती\",\n    this_will_appear_as_is: \"*हे जेनरेटेड स्क्रिप्टमध्ये जसे आहे तसेच दिसेल.\",\n    comment: \"टिप्पणी\",\n    add_field: \"फील्ड जोडा\",\n    values: \"व्हॅल्यूज\",\n    size: \"आकार\",\n    precision: \"तपशीलता\",\n    set_precision: \"तपशीलता सेट करा: (आकार, डिजिट्स)\",\n    use_for_batch_input: \"बॅच इनपुटसाठी वापरा\",\n    indices: \"इंडायसेस\",\n    add_index: \"इंडेक्स जोडा\",\n    select_fields: \"फील्ड्स निवडा\",\n    title: \"शीर्षक\",\n    not_set: \"सेट नाही\",\n    foreign: \"परदेशी\",\n    cardinality: \"कार्डिनॅलिटी\",\n    on_update: \"अपडेट वर\",\n    on_delete: \"हटवताना\",\n    swap: \"स्वॅप\",\n    one_to_one: \"एक ते एक\",\n    one_to_many: \"एक ते अनेक\",\n    many_to_one: \"अनेक ते एक\",\n    content: \"कंटेंट\",\n    types_info:\n      \"ही सुविधा object-relational DBMS जसे PostgreSQL साठी आहे.\\nMySQL किंवा MariaDB साठी वापरल्यास, एक JSON प्रकार जेनरेट केला जाईल ज्यात संबंधित json वैधता तपासणी असेल.\\nSQLite साठी वापरल्यास ते BLOB मध्ये रूपांतरित केले जाईल.\\nMSSQL साठी वापरल्यास प्रथम फील्डसाठी एक प्रकार उपनाम जेनरेट केला जाईल.\",\n    table_deleted: \"टेबल हटवले\",\n    area_deleted: \"क्षेत्र हटवले\",\n    note_deleted: \"नोंद हटवली\",\n    relationship_deleted: \"संबंध हटवला\",\n    type_deleted: \"प्रकार हटवला\",\n    cannot_connect: \"कनेक्ट करू शकत नाही, कॉलमचे प्रकार वेगवेगळे आहेत\",\n    copied_to_clipboard: \"क्लिपबोर्डवर कॉपी केले\",\n    create_new_diagram: \"नवीन डायग्राम तयार करा\",\n    cancel: \"रद्द करा\",\n    open_diagram: \"डायग्राम उघडा\",\n    rename_diagram: \"डायग्रामचे नाव बदला\",\n    export: \"निर्यात\",\n    export_image: \"इमेज निर्यात\",\n    create: \"तयार करा\",\n    confirm: \"पुष्टी करा\",\n    last_modified: \"शेवटचे बदलले\",\n    drag_and_drop_files:\n      \"फाइल येथे खेचा आणि सोडा किंवा अपलोड करण्यासाठी क्लिक करा.\",\n    upload_sql_to_generate_diagrams:\n      \"आपल्या टेबल आणि कॉलम स्वयंचलितपणे जेनरेट करण्यासाठी SQL फाइल अपलोड करा.\",\n    overwrite_existing_diagram: \"मौजूदा डायग्राम अधिलेखित करा\",\n    only_mysql_supported: \"*सध्या फक्त MySQL स्क्रिप्ट्स लोड करणे समर्थित आहे.\",\n    blank: \"रिक्त\",\n    filename: \"फाइलनाम\",\n    table_w_no_name: \"नाव नसलेल्या टेबलची घोषणा केली\",\n    duplicate_table_by_name: \"नावाने डुप्लिकेट टेबल '{{tableName}}'\",\n    empty_field_name: \"टेबल '{{tableName}}' मध्ये रिक्त फील्ड 'नाव'\",\n    empty_field_type: \"टेबल '{{tableName}}' मध्ये रिक्त फील्ड 'प्रकार'\",\n    no_values_for_field:\n      \"टेबल '{{tableName}}' च्या फील्ड '{{fieldName}}' चा प्रकार '{{type}}' आहे पण कोणतीही व्हॅल्यू निर्दिष्ट केलेली नाही\",\n    default_doesnt_match_type:\n      \"टेबल '{{tableName}}' च्या फील्ड '{{fieldName}}' ची डिफ़ॉल्ट व्हॅल्यू त्याच्या प्रकाराशी जुळत नाही\",\n    not_null_is_null:\n      \"टेबल '{{tableName}}' च्या फील्ड '{{fieldName}}' ची व्हॅल्यू NOT NULL आहे पण डिफ़ॉल्ट NULL आहे\",\n    duplicate_fields:\n      \"टेबल '{{tableName}}' मध्ये नाव '{{fieldName}}' असलेले डुप्लिकेट टेबल फील्ड्स\",\n    duplicate_index:\n      \"टेबल '{{tableName}}' मध्ये नाव '{{indexName}}' असलेला डुप्लिकेट इंडेक्स\",\n    empty_index:\n      \"टेबल '{{tableName}}' मध्ये इंडेक्स कोणताही कॉलम इंडेक्स करत नाही\",\n    no_primary_key: \"टेबल '{{tableName}}' मध्ये कोणतीही प्राथमिक कुंजी नाही\",\n    type_with_no_name: \"नाव नसलेला प्रकार घोषित केला\",\n    duplicate_types: \"नाव '{{typeName}}' असलेले डुप्लिकेट प्रकार\",\n    type_w_no_fields: \"कोणतेही फील्ड नसलेला प्रकार '{{typeName}}' घोषित केला\",\n    empty_type_field_name: \"प्रकार '{{typeName}}' मध्ये रिक्त फील्ड 'नाव'\",\n    empty_type_field_type: \"प्रकार '{{typeName}}' मध्ये रिक्त फील्ड 'प्रकार'\",\n    no_values_for_type_field:\n      \"प्रकार '{{typeName}}' च्या फील्ड '{{fieldName}}' चा प्रकार '{{type}}' आहे पण कोणतीही व्हॅल्यू निर्दिष्ट केलेली नाही\",\n    duplicate_type_fields:\n      \"प्रकार '{{typeName}}' मध्ये नाव '{{fieldName}}' असलेले डुप्लिकेट प्रकार फील्ड्स\",\n    duplicate_reference: \"नाव '{{refName}}' असलेला डुप्लिकेट संदर्भ\",\n    circular_dependency: \"टेबल '{{refName}}' मध्ये परिपत्रक अवलंबित्व\",\n    timeline: \"वेळरेखा\",\n    priority: \"प्राथमिकता\",\n    none: \"कोणतीही नाही\",\n    low: \"कमी\",\n    medium: \"मध्यम\",\n    high: \"उच्च\",\n    sort_by: \"क्रमानुसार\",\n    my_order: \"माझा क्रम\",\n    completed: \"पूर्ण\",\n    alphabetically: \"वर्णक्रमानुसार\",\n    add_task: \"कार्य जोडा\",\n    details: \"तपशील\",\n    no_tasks: \"आपल्याकडे अद्याप कोणतीही कार्ये नाहीत.\",\n    no_activity: \"आपल्याकडे अद्याप कोणतीही क्रियाकलाप नाही.\",\n    move_element: \"{{name}} ला {{coords}} वर हलवा\",\n    edit_area: \"{{extra}} संपादन क्षेत्र {{areaName}}\",\n    delete_area: \"क्षेत्र हटवा {{areaName}}\",\n    edit_note: \"{{extra}} नोंद संपादन करा {{noteTitle}}\",\n    delete_note: \"नोंद हटवा {{noteTitle}}\",\n    edit_table: \"{{extra}} टेबल संपादन करा {{tableName}}\",\n    delete_table: \"टेबल हटवा {{tableName}}\",\n    edit_type: \"{{extra}} प्रकार संपादन करा {{typeName}}\",\n    delete_type: \"प्रकार हटवा {{typeName}}\",\n    add_relationship: \"संबंध जोडा\",\n    edit_relationship: \"{{extra}} संबंध संपादन करा {{refName}}\",\n    delete_relationship: \"संबंध हटवा {{refName}}\",\n    pick_db: \"डेटाबेस निवडा\",\n    generic: \"जेनेरिक\",\n    generic_description:\n      \"जेनेरिक डायग्राम कोणत्याही SQL फ्लेवरमध्ये निर्यात केले जाऊ शकतात परंतु काही डेटा प्रकारांचे समर्थन करतात.\",\n    enums: \"इनम्स\",\n    add_enum: \"इनम जोडा\",\n    edit_enum: \"{{extra}} इनम संपादित करा {{enumName}}\",\n    delete_enum: \"इनम हटवा\",\n    enum_w_no_name: \"नाव नसलेला इनम सापडला\",\n    enum_w_no_values: \"'{{enumName}}' इनममध्ये कोणतीही व्हॅल्यू सापडली नाही\",\n    duplicate_enums: \"'{{enumName}}' नावाने डुप्लिकेट इनम्स\",\n    enum_deleted: \"इनम हटवले\",\n    no_enums: \"कोणतेही इनम्स नाहीत\",\n    no_enums_text: \"येथे इनम्स परिभाषित करा\",\n    declare_array: \"अ‍ॅरे घोषित करा\",\n    empty_index_name: \"टेबल '{{tableName}}' मध्ये नाव नसलेला इंडेक्स घोषित केला\",\n    didnt_find_diagram: \"अरे! डायग्राम सापडला नाही.\",\n    unsigned: \"चिन्ह नसलेले\",\n    share: \"शेअर करा\",\n    unshare: \"अनशेअर करा\",\n    copy_link: \"लिंक कॉपी करा\",\n    readme: \"README\",\n    failed_to_load: \"लोड करण्यात अयशस्वी. कृपया लिंक बरोबर असल्याची खात्री करा.\",\n    share_info:\n      \"* ही लिंक शेअर केल्याने लाइव्ह रिअल-टाइम सहयोग सत्र तयार होणार नाही.\",\n    show_relationship_labels: \"संबंध लेबल्स दाखवा\",\n    docs: \"दस्तऐवज\",\n    supported_types: \"समर्थित फाइल प्रकार:\",\n    bulk_update: \"बल्क अपडेट\",\n    multiselect: \"मल्टीसिलेक्ट\",\n    export_saved_data: \"जतन केलेला डेटा निर्यात करा\",\n    dbml_view: \"DBML दृश्य\",\n    tab_view: \"टॅब दृश्य\",\n    label: \"लेबल\",\n    many_side_label: \"अनेक(n) बाजूचे लेबल\",\n    version: \"आवृत्ती\",\n    versions: \"आवृत्त्या\",\n    no_saved_versions: \"कोणत्याही जतन केलेल्या आवृत्त्या नाहीत\",\n    record_version: \"आवृत्ती रेकॉर्ड करा\",\n    commited_at: \"कमिट केले\",\n    read_only: \"फक्त वाचनीय\",\n    continue: \"सुरू ठेवा\",\n    restore_version: \"आवृत्ती पुनर्संचयित करा\",\n    restore_warning: \"दुसरी आवृत्ती लोड केल्याने कोणतेही बदल अधिलिखित होतील.\",\n    return_to_current: \"डायग्रामवर परत जा\",\n    no_changes_to_record: \"रेकॉर्ड करण्यासाठी कोणतेही बदल नाहीत\",\n    click_to_view: \"पाहण्यासाठी क्लिक करा\",\n    load_more: \"आणखी लोड करा\",\n    clear_cache: \"कॅशे साफ करा\",\n    cache_cleared: \"कॅशे साफ केले\",\n    failed_to_record_version: \"आवृत्ती रेकॉर्ड करण्यात अयशस्वी\",\n    failed_to_load_diagram: \"डायग्राम लोड करण्यात अयशस्वी\",\n    see_all: \"सर्व पहा\",\n    insert_sql: \"SQL घाला\",\n    upload_file: \"फाइल अपलोड करा\",\n    not_found: \"सापडले नाही\",\n    inherits: \"वारसा मिळतो\",\n    merging_column_w_inherited_definition: \"टेबल '{{tableName}}' मधील कॉलम '{{fieldName}}' वारसाहक्काने मिळालेल्या व्याख्येसह विलीन केला जाईल\",\n    nullable: \"नल असू शकते\",\n  },\n};\n\nexport { mr, marathi };\n"
  },
  {
    "path": "src/i18n/locales/ms.js",
    "content": "const malay = {\n  name: \"Malay\",\n  native_name: \"Bahasa Melayu\",\n  code: \"ms\",\n};\n\nconst ms = {\n  translation: {\n    report_bug: \"Laporkan pepijat\",\n    import_from: \"Import dari\",\n    import: \"Import\",\n    file: \"Fail\",\n    new: \"Baru\",\n    new_window: \"Tetingkap baru\",\n    open: \"Buka\",\n    open_recent: \"Buka terkini\",\n    no_saved_diagrams: \"Anda tiada rajah yang disimpan\",\n    save: \"Simpan\",\n    save_as: \"Simpan sebagai\",\n    save_as_template: \"Simpan sebagai templat\",\n    template_saved: \"Templat disimpan!\",\n    rename: \"Namakan semula\",\n    delete_diagram: \"Padam rajah\",\n    are_you_sure_delete_diagram:\n      \"Adakah anda pasti mahu memadam rajah ini? Tindakan ini tidak boleh dipulihkan.\",\n    oops_smth_went_wrong: \"Ooops! Ada sesuatu yang tidak kena.\",\n    import_diagram: \"Import rajah\",\n    import_from_source: \"Import dari SQL\",\n    export_as: \"Eksport sebagai\",\n    export_source: \"Eksport SQL\",\n    models: \"Model\",\n    exit: \"Keluar\",\n    edit: \"Sunting\",\n    undo: \"Batal\",\n    redo: \"Ulang\",\n    clear: \"Kosongkan\",\n    are_you_sure_clear:\n      \"Adakah anda pasti mahu mengosongkan rajah ini? Tindakan ini tidak boleh dipulihkan.\",\n    cut: \"Potong\",\n    copy: \"Salin\",\n    paste: \"Tampal\",\n    duplicate: \"Duplikat\",\n    delete: \"Padam\",\n    copy_as_image: \"Salin sebagai imej\",\n    view: \"Paparan\",\n    header: \"Bar menu\",\n    sidebar: \"Bar sisi\",\n    issues: \"Isu\",\n    presentation_mode: \"Mod pembentangan\",\n    strict_mode: \"Mod ketat\",\n    field_details: \"Butiran medan\",\n    reset_view: \"Set semula paparan\",\n    show_grid: \"Tunjuk grid\",\n    snap_to_grid: \"Lekat pada grid\",\n    show_datatype: \"Tunjuk jenis data\",\n    show_cardinality: \"Tunjuk kardinaliti\",\n    theme: \"Tema\",\n    light: \"Terang\",\n    dark: \"Gelap\",\n    zoom_in: \"Zum masuk\",\n    zoom_out: \"Zum keluar\",\n    fullscreen: \"Skrin penuh\",\n    settings: \"Tetapan\",\n    show_timeline: \"Tunjuk garis masa\",\n    autosave: \"Simpan automatik\",\n    panning: \"Seret (panning)\",\n    show_debug_coordinates: \"Tunjuk koordinat penyahpepijat\",\n    transform: \"Transformasi\",\n    viewbox: \"Kotak pandang\",\n    cursor_coordinates: \"Koordinat kursor\",\n    coordinate_space: \"Ruang koordinat\",\n    coordinate_space_screen: \"Skrin\",\n    coordinate_space_diagram: \"Rajah\",\n    table_width: \"Lebar jadual\",\n    language: \"Bahasa\",\n    flush_storage: \"Kosongkan storan\",\n    are_you_sure_flush_storage:\n      \"Adakah anda pasti mahu kosongkan storan? Ini akan memadamkan semua rajah dan templat tersuai anda secara kekal.\",\n    storage_flushed: \"Storan dikosongkan\",\n    help: \"Bantuan\",\n    shortcuts: \"Pintas kekunci\",\n    ask_on_discord: \"Tanya kami di Discord\",\n    feedback: \"Maklum balas\",\n    no_changes: \"Tiada perubahan\",\n    loading: \"Memuatkan...\",\n    last_saved: \"Terakhir disimpan\",\n    saving: \"Menyimpan...\",\n    failed_to_save: \"Gagal menyimpan\",\n    fit_window_reset: \"Sesuaikan / set semula tingkap\",\n    zoom: \"Zum\",\n    add_table: \"Tambah jadual\",\n    add_area: \"Tambah kawasan\",\n    add_note: \"Tambah nota\",\n    add_type: \"Tambah jenis\",\n    to_do: \"Perkara perlu dibuat\",\n    tables: \"Jadual\",\n    relationships: \"Perhubungan\",\n    subject_areas: \"Kawasan subjek\",\n    notes: \"Nota\",\n    types: \"Jenis\",\n    search: \"Cari...\",\n    no_tables: \"Tiada jadual\",\n    no_tables_text: \"Mulakan dengan mencipta rajah anda!\",\n    no_relationships: \"Tiada perhubungan\",\n    no_relationships_text: \"Seret untuk sambungkan medan dan bina perhubungan!\",\n    no_subject_areas: \"Tiada kawasan subjek\",\n    no_subject_areas_text: \"Tambah kawasan subjek untuk kumpulkan jadual!\",\n    no_notes: \"Tiada nota\",\n    no_notes_text: \"Gunakan nota untuk maklumat tambahan\",\n    no_types: \"Tiada jenis\",\n    no_types_text: \"Cipta jenis data tersuai anda sendiri\",\n    no_issues: \"Tiada isu ditemui.\",\n    strict_mode_is_on_no_issues:\n      \"Mod ketat diaktifkan, jadi isu tidak akan dipaparkan.\",\n    name: \"Nama\",\n    type: \"Jenis\",\n    null: \"Null\",\n    not_null: \"Not Null\",\n    primary: \"Utama\",\n    unique: \"Unik\",\n    autoincrement: \"Auto-increment\",\n    default_value: \"Nilai lalai\",\n    check: \"Ungkapan semakan\",\n    this_will_appear_as_is:\n      \"*Ini akan dipaparkan seperti sedia ada dalam skrip yang dijana.\",\n    comment: \"Komen\",\n    add_field: \"Tambah medan\",\n    values: \"Nilai\",\n    size: \"Saiz\",\n    precision: \"Ketepatan\",\n    set_precision: \"Tetapkan ketepatan: (saiz, digit)\",\n    use_for_batch_input: \"Gunakan untuk input berkelompok\",\n    indices: \"Indeks\",\n    add_index: \"Tambah indeks\",\n    select_fields: \"Pilih medan\",\n    title: \"Tajuk\",\n    not_set: \"Belum ditetapkan\",\n    foreign: \"Luaran\",\n    cardinality: \"Kardinaliti\",\n    on_update: \"Semasa kemas kini\",\n    on_delete: \"Semasa padam\",\n    swap: \"Tukar\",\n    one_to_one: \"Satu kepada satu\",\n    one_to_many: \"Satu kepada banyak\",\n    many_to_one: \"Banyak kepada satu\",\n    content: \"Kandungan\",\n    types_info:\n      \"Ciri ini untuk DBMS berorientasikan objek seperti PostgreSQL.\\nUntuk MySQL/MariaDB, jenis JSON akan dijana dengan pemeriksaan kesahihan JSON.\\nUntuk SQLite ia akan ditukar kepada BLOB.\\nUntuk MSSQL alias jenis akan dijana untuk medan pertama.\",\n    table_deleted: \"Jadual dipadam\",\n    area_deleted: \"Kawasan dipadam\",\n    note_deleted: \"Nota dipadam\",\n    relationship_deleted: \"Perhubungan dipadam\",\n    type_deleted: \"Jenis dipadam\",\n    cannot_connect: \"Tidak boleh sambung — jenis lajur berbeza\",\n    copied_to_clipboard: \"Disalin ke papan klip\",\n    create_new_diagram: \"Cipta rajah baru\",\n    cancel: \"Batal\",\n    open_diagram: \"Buka rajah\",\n    rename_diagram: \"Namakan semula rajah\",\n    export: \"Eksport\",\n    export_image: \"Eksport imej\",\n    create: \"Cipta\",\n    confirm: \"Sahkan\",\n    last_modified: \"Terakhir diubah\",\n    drag_and_drop_files:\n      \"Seret dan lepaskan fail di sini atau klik untuk muat naik.\",\n    upload_sql_to_generate_diagrams:\n      \"Muat naik fail SQL untuk jana automatik jadual dan lajur anda.\",\n    overwrite_existing_diagram: \"Tulis ganti rajah sedia ada\",\n    only_mysql_supported:\n      \"*Buangan skrip hanya menyokong muatan skrip MySQL buat masa ini.\",\n    blank: \"Kosong\",\n    filename: \"Nama fail\",\n    table_w_no_name: \"Jadual diisytiharkan tanpa nama\",\n    duplicate_table_by_name: \"Duplikasi jadual dengan nama '{{tableName}}'\",\n    empty_field_name: \"Nama medan kosong dalam jadual '{{tableName}}'\",\n    empty_field_type: \"Jenis medan kosong dalam jadual '{{tableName}}'\",\n    no_values_for_field:\n      \"Medan '{{fieldName}}' dalam jadual '{{tableName}}' mempunyai jenis '{{type}}' tetapi tiada nilai ditetapkan\",\n    default_doesnt_match_type:\n      \"Nilai lalai untuk medan '{{fieldName}}' dalam jadual '{{tableName}}' tidak padan dengan jenisnya\",\n    not_null_is_null:\n      \"Medan '{{fieldName}}' dalam jadual '{{tableName}}' ditetapkan NOT NULL tetapi nilai lalai adalah NULL\",\n    duplicate_fields:\n      \"Medan berganda bernama '{{fieldName}}' dalam jadual '{{tableName}}'\",\n    duplicate_index:\n      \"Indeks berganda bernama '{{indexName}}' dalam jadual '{{tableName}}'\",\n    empty_index: \"Indeks dalam jadual '{{tableName}}' tiada lajur\",\n    no_primary_key: \"Tiada kekunci primer dalam jadual '{{tableName}}'\",\n    type_with_no_name: \"Jenis diisytiharkan tanpa nama\",\n    duplicate_types: \"Jenis berganda bernama '{{typeName}}'\",\n    type_w_no_fields: \"Jenis '{{typeName}}' diisytiharkan tanpa medan\",\n    empty_type_field_name: \"Nama medan jenis kosong dalam jenis '{{typeName}}'\",\n    empty_type_field_type:\n      \"Jenis medan jenis kosong dalam jenis '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Medan '{{fieldName}}' jenis '{{typeName}}' mempunyai jenis '{{type}}' tetapi tiada nilai ditetapkan\",\n    duplicate_type_fields:\n      \"Medan jenis berganda bernama '{{fieldName}}' dalam jenis '{{typeName}}'\",\n    duplicate_reference: \"Rujukan berganda bernama '{{refName}}'\",\n    circular_dependency: \"Kebergantungan berputar dalam jadual '{{refName}}'\",\n    timeline: \"Garis masa\",\n    priority: \"Keutamaan\",\n    none: \"Tiada\",\n    low: \"Rendah\",\n    medium: \"Sederhana\",\n    high: \"Tinggi\",\n    sort_by: \"Susun mengikut\",\n    my_order: \"Susunan saya\",\n    completed: \"Selesai\",\n    alphabetically: \"Secara abjad\",\n    add_task: \"Tambah tugasan\",\n    details: \"Perincian\",\n    no_tasks: \"Anda belum mempunyai tugasan.\",\n    no_activity: \"Tiada aktiviti lagi.\",\n    move_element: \"Pindahkan {{name}} ke {{coords}}\",\n    edit_area: \"{{extra}} Edit kawasan {{areaName}}\",\n    delete_area: \"Padam kawasan {{areaName}}\",\n    edit_note: \"{{extra}} Edit nota {{noteTitle}}\",\n    delete_note: \"Padam nota {{noteTitle}}\",\n    edit_table: \"{{extra}} Edit jadual {{tableName}}\",\n    delete_table: \"Padam jadual {{tableName}}\",\n    edit_type: \"{{extra}} Edit jenis {{typeName}}\",\n    delete_type: \"Padam jenis {{typeName}}\",\n    add_relationship: \"Tambah perhubungan\",\n    edit_relationship: \"{{extra}} Edit perhubungan {{refName}}\",\n    delete_relationship: \"Padam perhubungan {{refName}}\",\n    pick_db: \"Pilih pangkalan data\",\n    generic: \"Generik\",\n    generic_description:\n      \"Rajah generik boleh dieksport ke mana-mana dialek SQL, tetapi tidak semua jenis data disokong.\",\n    enums: \"Enum\",\n    add_enum: \"Tambah enum\",\n    edit_enum: \"{{extra}} Edit enum {{enumName}}\",\n    delete_enum: \"Padam enum\",\n    enum_w_no_name: \"Ditemui enum tanpa nama\",\n    enum_w_no_values: \"Tiada nilai untuk enum '{{enumName}}'\",\n    duplicate_enums: \"Enum berganda bernama '{{enumName}}'\",\n    enum_deleted: \"Enum dipadam\",\n    no_enums: \"Tiada enum\",\n    no_enums_text: \"Tentukan enum di sini\",\n    declare_array: \"Isytihar tatasusunan\",\n    empty_index_name:\n      \"Indeks diisytiharkan tanpa nama dalam jadual '{{tableName}}'\",\n    didnt_find_diagram: \"Ooops! Rajah tidak dijumpai.\",\n    unsigned: \"Tanpa tanda\",\n    share: \"Kongsi\",\n    unshare: \"Batalkan kongsi\",\n    copy_link: \"Salin pautan\",\n    readme: \"README\",\n    failed_to_load: \"Gagal memuatkan. Sila pastikan pautan betul.\",\n    share_info:\n      \"* Kongsi pautan ini tidak mewujudkan sesi kolaborasi masa nyata.\",\n    show_relationship_labels: \"Tunjuk label perhubungan\",\n    docs: \"Dokumentasi\",\n    supported_types: \"Jenis fail yang disokong:\",\n    bulk_update: \"Kemas kini besar-besaran\",\n    multiselect: \"Pemilihan berbilang\",\n    export_saved_data: \"Eksport data tersimpan\",\n    dbml_view: \"Paparan DBML\",\n    tab_view: \"Paparan tab\",\n    label: \"Label\",\n    many_side_label: \"Label sisi banyak (n)\",\n    version: \"Versi\",\n    versions: \"Versi\",\n    no_saved_versions: \"Tiada versi disimpan\",\n    record_version: \"Rekod versi\",\n    commited_at: \"Dikomit pada\",\n    read_only: \"Baca sahaja\",\n    continue: \"Teruskan\",\n    restore_version: \"Pulihkan versi\",\n    restore_warning:\n      \"Memuatkan versi lain akan menulis ganti sebarang perubahan.\",\n    return_to_current: \"Kembali ke rajah semasa\",\n    no_changes_to_record: \"Tiada perubahan untuk direkod\",\n    click_to_view: \"Klik untuk lihat\",\n    load_more: \"Muatkan lagi\",\n    clear_cache: \"Kosongkan cache\",\n    cache_cleared: \"Cache dikosongkan\",\n    failed_to_record_version: \"Gagal merekod versi\",\n    failed_to_load_diagram: \"Gagal memuatkan rajah\",\n    see_all: \"Lihat semua\",\n    insert_sql: \"Masukkan SQL\",\n    upload_file: \"Muat naik fail\",\n    not_found: \"Tidak dijumpai\",\n  },\n};\n\nexport { ms, malay };\n"
  },
  {
    "path": "src/i18n/locales/ne.js",
    "content": "const nepali = {\n  name: \"Nepali\",\n  native_name: \"नेपाली\",\n  code: \"ne\",\n};\n\nconst ne = {\n  translation: {\n    report_bug: \"बग रिपोर्ट गर्नुहोस्\",\n    import_from: \"इम्पोर्ट गर्नुहोस्\",\n    import: \"इम्पोर्ट गर्नुहोस्\",\n    file: \"फाइल\",\n    new: \"नयाँ\",\n    new_window: \"नयाँ विन्डो\",\n    open: \"खोल्नुहोस्\",\n    open_recent: \"हालै खोलिएका\",\n    save: \"सेभ गर्नुहोस्\",\n    save_as: \"यो रूपमा सेभ गर्नुहोस्\",\n    save_as_template: \"टेम्पलेट रूपमा सेभ गर्नुहोस्\",\n    template_saved: \"टेम्पलेट सेभ गरियो!\",\n    rename: \"नाम परिवर्तन गर्नुहोस्\",\n    no_saved_diagrams: \"तपाईंका सेभ गरिएका डायग्राम छैनन्।\",\n    delete_diagram: \"डायग्राम मेटाउनुहोस्\",\n    are_you_sure_delete_diagram:\n      \"के तपाईं पक्का यो डायग्राम मेटाउन चाहनुहुन्छ? यो कार्य पुनः प्राप्त गर्न सकिँदैन।\",\n    oops_smth_went_wrong: \"उफ! केहि गलत भयो।\",\n    import_diagram: \"डायग्राम इम्पोर्ट गर्नुहोस्\",\n    import_from_source: \"स्रोतबाट इम्पोर्ट गर्नुहोस्\",\n    export_as: \"यो रूपमा एक्सपोर्ट गर्नुहोस्\",\n    export_source: \"स्रोत एक्सपोर्ट गर्नुहोस्\",\n    models: \"मोडल्स\",\n    exit: \"निस्कनुहोस्\",\n    edit: \"सम्पादन गर्नुहोस्\",\n    undo: \"पूर्ववत गर्नुहोस्\",\n    redo: \"पुन: गर्नुहोस्\",\n    clear: \"सफा गर्नुहोस्\",\n    are_you_sure_clear:\n      \"के तपाईं पक्का यो डायग्राम सफा गर्न चाहनुहुन्छ? यो पुनः प्राप्त गर्न सकिँदैन।\",\n    cut: \"काट्नुहोस्\",\n    copy: \"कपी गर्नुहोस्\",\n    paste: \"पेस्ट गर्नुहोस्\",\n    duplicate: \"डुप्लिकेट गर्नुहोस्\",\n    delete: \"मेटाउनुहोस्\",\n    copy_as_image: \"छविको रूपमा कपी गर्नुहोस्\",\n    view: \"दृश्य\",\n    header: \"हेडर\",\n    sidebar: \"साइडबार\",\n    issues: \"समस्याहरू\",\n    presentation_mode: \"प्रस्तुति मोड\",\n    strict_mode: \"स्ट्रिक्ट मोड\",\n    field_details: \"फिल्ड विवरणहरू\",\n    reset_view: \"दृश्य रिसेट गर्नुहोस्\",\n    show_grid: \"ग्रिड देखाउनुहोस्\",\n    show_cardinality: \"कार्डिनालिटी देखाउनुहोस्\",\n    theme: \"थीम\",\n    light: \"प्रकाश\",\n    dark: \"अँध्यारो\",\n    zoom_in: \"जुम इन गर्नुहोस्\",\n    zoom_out: \"जुम आउट गर्नुहोस्\",\n    fullscreen: \"पूर्ण स्क्रिन\",\n    settings: \"सेटिङ्स\",\n    show_timeline: \"टाइमलाइन देखाउनुहोस्\",\n    autosave: \"स्वतः सेभ\",\n    panning: \"प्यानिङ\",\n    table_width: \"टेबल चौडाइ\",\n    language: \"भाषा\",\n    flush_storage: \"स्टोरेज सफा गर्नुहोस्\",\n    are_you_sure_flush_storage:\n      \"के तपाईं पक्का स्टोरेज सफा गर्न चाहनुहुन्छ? यसले तपाईंको सबै डायग्राम र कस्टम टेम्पलेटहरू स्थायी रूपमा मेटाउँछ।\",\n    storage_flushed: \"स्टोरेज सफा गरियो\",\n    help: \"मद्दत\",\n    shortcuts: \"शॉर्टकटहरू\",\n    ask_on_discord: \"हामीलाई Discord मा सोध्नुहोस्\",\n    feedback: \"प्रतिक्रिया\",\n    no_changes: \"कुनै परिवर्तन छैन\",\n    loading: \"लोड हुँदैछ...\",\n    last_saved: \"अन्तिम सेभ गरिएको\",\n    saving: \"सेभ गर्दैछ...\",\n    failed_to_save: \"सेभ गर्न असफल\",\n    fit_window_reset: \"विन्डो फिट गर्नुहोस् / रिसेट गर्नुहोस्\",\n    zoom: \"जुम\",\n    add_table: \"टेबल थप्नुहोस्\",\n    add_area: \"क्षेत्र थप्नुहोस्\",\n    add_note: \"नोट थप्नुहोस्\",\n    add_type: \"प्रकार थप्नुहोस्\",\n    to_do: \"गर्नु पर्ने\",\n    tables: \"टेबलहरू\",\n    relationships: \"सम्बन्धहरू\",\n    subject_areas: \"विषय क्षेत्रहरू\",\n    notes: \"नोटहरू\",\n    types: \"प्रकारहरू\",\n    search: \"खोज्नुहोस्...\",\n    no_tables: \"कुनै टेबलहरू छैनन्\",\n    no_tables_text: \"आफ्नो डायग्राम बनाउन सुरु गर्नुहोस्!\",\n    no_relationships: \"कुनै सम्बन्धहरू छैनन्\",\n    no_relationships_text: \"फिल्डहरू जोड्न तानेर सम्बन्ध बनाउनुहोस्!\",\n    no_subject_areas: \"कुनै विषय क्षेत्रहरू छैनन्\",\n    no_subject_areas_text: \"टेबलहरू समूह गर्न विषय क्षेत्रहरू थप्नुहोस्!\",\n    no_notes: \"कुनै नोटहरू छैनन्\",\n    no_notes_text: \"थप जानकारी रेकर्ड गर्न नोटहरू प्रयोग गर्नुहोस्\",\n    no_types: \"कुनै प्रकारहरू छैनन्\",\n    no_types_text: \"आफ्नो कस्टम डेटा प्रकारहरू बनाउनुहोस्\",\n    no_issues: \"कुनै समस्या पाइएको छैन।\",\n    strict_mode_is_on_no_issues:\n      \"स्ट्रिक्ट मोड बन्द छ त्यसैले कुनै समस्या देखाइने छैन।\",\n    name: \"नाम\",\n    type: \"प्रकार\",\n    null: \"नल\",\n    not_null: \"नल होइन\",\n    primary: \"प्राथमिक\",\n    unique: \"युनिक\",\n    autoincrement: \"स्वतः वृद्धि\",\n    default_value: \"डिफल्ट\",\n    check: \"चेक अभिव्यक्ति\",\n    this_will_appear_as_is:\n      \"*यो जेनरेट गरिएको स्क्रिप्टमा जसरी हुन्छ त्यस्तै देखिनेछ।\",\n    comment: \"टिप्पणी\",\n    add_field: \"फिल्ड थप्नुहोस्\",\n    values: \"मानहरू\",\n    size: \"आकार\",\n    precision: \"सटीकता\",\n    set_precision: \"सटीकता सेट गर्नुहोस्: (आकार, अंकहरू)\",\n    use_for_batch_input: \"ब्याच इनपुटका लागि प्रयोग गर्नुहोस्\",\n    indices: \"इन्डिसहरू\",\n    add_index: \"इन्डेक्स थप्नुहोस्\",\n    select_fields: \"फिल्डहरू चयन गर्नुहोस्\",\n    title: \"शीर्षक\",\n    not_set: \"सेट गरिएको छैन\",\n    foreign: \"विदेशी\",\n    cardinality: \"कार्डिनालिटी\",\n    on_update: \"अपडेट गर्दा\",\n    on_delete: \"मेटाउँदा\",\n    swap: \"स्वैप\",\n    one_to_one: \"एक देखि एक\",\n    one_to_many: \"एक देखि धेरै\",\n    many_to_one: \"धेरै देखि एक\",\n    content: \"सामग्री\",\n    types_info:\n      \"यो सुविधा object-relational DBMS जस्तै PostgreSQL का लागि हो।\\nयदि MySQL वा MariaDB का लागि प्रयोग गरिन्छ भने, एक JSON प्रकार उत्पन्न हुनेछ।\\nयदि SQLite का लागि प्रयोग गरिन्छ भने यसलाई BLOB मा परिणत गरिनेछ।\\nयदि MSSQL का लागि प्रयोग गरिन्छ भने प्रकार उपनाम बनाइनेछ।\",\n    table_deleted: \"टेबल मेटाइयो\",\n    area_deleted: \"क्षेत्र मेटाइयो\",\n    note_deleted: \"नोट मेटाइयो\",\n    relationship_deleted: \"सम्बन्ध मेटाइयो\",\n    type_deleted: \"प्रकार मेटाइयो\",\n    cannot_connect: \"जोड्न सकिँदैन, कॉलम प्रकारहरू फरक छन्\",\n    copied_to_clipboard: \"क्लिपबोर्डमा कपी गरियो\",\n    create_new_diagram: \"नयाँ डायग्राम बनाउनुहोस्\",\n    cancel: \"रद्द गर्नुहोस्\",\n    open_diagram: \"डायग्राम खोल्नुहोस्\",\n    rename_diagram: \"डायग्रामको नाम परिवर्तन गर्नुहोस्\",\n    export: \"एक्सपोर्ट\",\n    export_image: \"इमेज एक्सपोर्ट गर्नुहोस्\",\n    create: \"बनाउनुहोस्\",\n    confirm: \"पुष्टि गर्नुहोस्\",\n    last_modified: \"अन्तिम पटक संशोधित\",\n    drag_and_drop_files:\n      \"फाइललाई यहाँ तानेर छोड्नुहोस् वा अपलोड गर्न क्लिक गर्नुहोस्।\",\n    upload_sql_to_generate_diagrams:\n      \"स्वचालित रूपमा डायग्राम सिर्जना गर्न SQL फाइल अपलोड गर्नुहोस्।\",\n    overwrite_existing_diagram: \"मौजुदा डायग्रामलाई अधिलेखित गर्नुहोस्\",\n    only_mysql_supported:\n      \"*हालको लागि केवल MySQL स्क्रिप्टहरू मात्र समर्थित छन्।\",\n    blank: \"खाली\",\n    filename: \"फाइल नाम\",\n    table_w_no_name: \"नाम बिना टेबल घोषणा गरियो\",\n    duplicate_table_by_name: \"नामद्वारा डुप्लिकेट टेबल '{{tableName}}'\",\n    empty_field_name: \"टेबल '{{tableName}}' मा खाली फिल्ड `नाम`\",\n    empty_field_type: \"टेबल '{{tableName}}' मा खाली फिल्ड `प्रकार`\",\n    no_values_for_field:\n      \"तालिका '{{tableName}}' को क्षेत्र '{{fieldName}}' को प्रकार `{{type}}` हो तर कुनै मान निर्दिष्ट गरिएको छैन\",\n    default_doesnt_match_type:\n      \"तालिका '{{tableName}}' मा क्षेत्र '{{fieldName}}' को डिफ़ल्ट मान यसको प्रकारसँग मेल खाँदैन\",\n    not_null_is_null:\n      \"तालिका '{{tableName}}' को क्षेत्र '{{fieldName}}' को मान NOT NULL हो तर डिफ़ल्ट NULL छ\",\n    duplicate_fields:\n      \"तालिका '{{tableName}}' मा नाम '{{fieldName}}' भएका दोहोरो तालिका क्षेत्रहरू\",\n    duplicate_index:\n      \"तालिका '{{tableName}}' मा नाम '{{indexName}}' भएको दोहोरो सूची\",\n    empty_index:\n      \"तालिका '{{tableName}}' मा सूची कुनै पनि स्तम्भ सूची गरिरहेको छैन\",\n    no_primary_key: \"तालिका '{{tableName}}' मा कुनै प्रमुख कुञ्जी छैन\",\n    type_with_no_name: \"कुनै नाम नभएको प्रकार घोषण गरिएको छ\",\n    duplicate_types: \"नाम '{{typeName}}' भएका दोहोरो प्रकार\",\n    type_w_no_fields: \"कुनै क्षेत्र नभएको प्रकार '{{typeName}}' घोषण गरिएको छ\",\n    empty_type_field_name: \"प्रकार '{{typeName}}' मा खाली क्षेत्र `नाम`\",\n    empty_type_field_type: \"प्रकार '{{typeName}}' मा खाली क्षेत्र `प्रकार`\",\n    no_values_for_type_field:\n      \"प्रकार '{{typeName}}' को क्षेत्र '{{fieldName}}' को प्रकार `{{type}}` हो तर कुनै मान निर्दिष्ट गरिएको छैन\",\n    duplicate_type_fields:\n      \"प्रकार '{{typeName}}' मा नाम '{{fieldName}}' भएका दोहोरो प्रकार क्षेत्रहरू\",\n    duplicate_reference: \"नाम '{{refName}}' भएको दोहोरो सन्दर्भ\",\n    circular_dependency: \"तालिका '{{refName}}' मा वृत्तीय निर्भरता\",\n    timeline: \"समयरेखा\",\n    priority: \"प्राथमिकता\",\n    none: \"कुनै होइन\",\n    low: \"निम्न\",\n    medium: \"मध्यम\",\n    high: \"उच्च\",\n    sort_by: \"द्वारा क्रमबद्ध गर्नुहोस्\",\n    my_order: \"मेरो क्रम\",\n    completed: \"पूरा\",\n    alphabetically: \"वर्णानुक्रममा\",\n    add_task: \"कार्य थप्नुहोस्\",\n    details: \"विवरण\",\n    no_tasks: \"तपाईंलाई हालसम्म कुनै कार्य छैन।\",\n    no_activity: \"तपाईंलाई हालसम्म कुनै गतिविधि छैन।\",\n    move_element: \"{{name}} लाई {{coords}} मा सार्नुहोस्\",\n    edit_area: \"{{extra}} क्षेत्र सम्पादन गर्नुहोस् {{areaName}}\",\n    delete_area: \"क्षेत्र मेटाउनुहोस् {{areaName}}\",\n    edit_note: \"{{extra}} नोट सम्पादन गर्नुहोस् {{noteTitle}}\",\n    delete_note: \"नोट मेटाउनुहोस् {{noteTitle}}\",\n    edit_table: \"{{extra}} तालिका सम्पादन गर्नुहोस् {{tableName}}\",\n    delete_table: \"तालिका मेटाउनुहोस् {{tableName}}\",\n    edit_type: \"{{extra}} प्रकार सम्पादन गर्नुहोस् {{typeName}}\",\n    delete_type: \"प्रकार मेटाउनुहोस् {{typeName}}\",\n    add_relationship: \"संबन्ध थप्नुहोस्\",\n    edit_relationship: \"{{extra}} सम्बन्ध सम्पादन गर्नुहोस् {{refName}}\",\n    delete_relationship: \"संबन्ध मेटाउनुहोस् {{refName}}\",\n    didnt_find_diagram: \"उफ! डायग्राम फेला परेन।\",\n    not_found: \"फेला परेन\",\n    see_all: \"सबै देखाउनुहोस्\",\n    versions: \"संस्करणहरू\",\n  },\n};\n\nexport { ne, nepali };\n"
  },
  {
    "path": "src/i18n/locales/nl.js",
    "content": "const dutch = {\n  name: \"Dutch\",\n  native_name: \"Nederlands\",\n  code: \"nl\",\n};\n\nconst nl = {\n  translation: {\n    report_bug: \"Meld een bug\",\n    import: \"Importeren\",\n    inherits: \"Erft van\",\n    merging_column_w_inherited_definition:\n      \"Kolom '{{fieldName}}' in tabel '{{tableName}}' met overgeërfde definitie zal worden samengevoegd\",\n    import_from: \"Importeren van\",\n    file: \"Bestand\",\n    new: \"Nieuw\",\n    new_window: \"Nieuw venster\",\n    no_saved_diagrams: \"U heeft geen opgeslagen diagrammen\",\n    open: \"Openen\",\n    open_recent: \"Recent openen\",\n    save: \"Opslaan\",\n    save_as: \"Opslaan als\",\n    save_as_template: \"Opslaan als sjabloon\",\n    template_saved: \"Sjabloon opgeslagen!\",\n    rename: \"Hernoemen\",\n    delete_diagram: \"Diagram verwijderen\",\n    are_you_sure_delete_diagram:\n      \"Weet u zeker dat u dit diagram wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.\",\n    oops_smth_went_wrong: \"Oeps! Er is iets misgegaan.\",\n    import_diagram: \"Diagram importeren\",\n    import_from_source: \"Importeren van SQL\",\n    export_as: \"Exporteren als\",\n    export_source: \"SQL exporteren\",\n    models: \"Modellen\",\n    exit: \"Afsluiten\",\n    edit: \"Bewerken\",\n    undo: \"Ongedaan maken\",\n    redo: \"Opnieuw uitvoeren\",\n    clear: \"Wissen\",\n    are_you_sure_clear:\n      \"Weet u zeker dat u het diagram wilt wissen? Deze actie kan niet ongedaan worden gemaakt.\",\n    cut: \"Knippen\",\n    copy: \"Kopiëren\",\n    paste: \"Plakken\",\n    duplicate: \"Dupliceren\",\n    delete: \"Verwijderen\",\n    copy_as_image: \"Kopiëren als afbeelding\",\n    view: \"Beeld\",\n    header: \"Menubalk\",\n    sidebar: \"Zijbalk\",\n    issues: \"Problemen\",\n    presentation_mode: \"Presentatiemodus\",\n    strict_mode: \"Strikte modus\",\n    field_details: \"Veld details\",\n    reset_view: \"Beeld resetten\",\n    show_grid: \"Raster tonen\",\n    snap_to_grid: \"Aan raster vastmaken\",\n    show_datatype: \"Gegevenstype tonen\",\n    show_cardinality: \"Kardinaliteit tonen\",\n    theme: \"Thema\",\n    light: \"Licht\",\n    dark: \"Donker\",\n    zoom_in: \"Inzoomen\",\n    zoom_out: \"Uitzoomen\",\n    fullscreen: \"Volledig scherm\",\n    settings: \"Instellingen\",\n    show_timeline: \"Tijdlijn tonen\",\n    autosave: \"Automatisch opslaan\",\n    panning: \"Pannen\",\n    show_debug_coordinates: \"Debug-coördinaten tonen\",\n    transform: \"Transformeren\",\n    viewbox: \"Weergavekader\",\n    cursor_coordinates: \"Cursorcoördinaten\",\n    coordinate_space: \"Ruimte\",\n    coordinate_space_screen: \"Scherm\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Tabelbreedte\",\n    language: \"Taal\",\n    flush_storage: \"Opslag legen\",\n    are_you_sure_flush_storage:\n      \"Weet u zeker dat u de opslag wilt legen? Dit zal onomkeerbaar al uw diagrammen en aangepaste sjablonen verwijderen.\",\n    storage_flushed: \"Opslag geleegd\",\n    help: \"Help\",\n    shortcuts: \"Sneltoetsen\",\n    ask_on_discord: \"Vraag het ons op Discord\",\n    feedback: \"Feedback\",\n    no_changes: \"Geen wijzigingen\",\n    loading: \"Laden...\",\n    last_saved: \"Laatst opgeslagen\",\n    saving: \"Opslaan...\",\n    failed_to_save: \"Opslaan mislukt\",\n    fit_window_reset: \"Passend maken / Resetten\",\n    zoom: \"Zoom\",\n    add_table: \"Tabel toevoegen\",\n    add_area: \"Gebied toevoegen\",\n    add_note: \"Notitie toevoegen\",\n    add_type: \"Type toevoegen\",\n    to_do: \"To-do\",\n    tables: \"Tabellen\",\n    relationships: \"Relaties\",\n    subject_areas: \"Onderwerpsgebieden\",\n    notes: \"Notities\",\n    types: \"Types\",\n    search: \"Zoeken...\",\n    no_tables: \"Geen tabellen\",\n    no_tables_text: \"Begin met het bouwen van uw diagram!\",\n    no_relationships: \"Geen relaties\",\n    no_relationships_text: \"Sleep om velden te verbinden en relaties te vormen!\",\n    no_subject_areas: \"Geen onderwerpsgebieden\",\n    no_subject_areas_text: \"Voeg onderwerpsgebieden toe om tabellen te groeperen!\",\n    no_notes: \"Geen notities\",\n    no_notes_text: \"Gebruik notities om extra informatie vast te leggen\",\n    no_types: \"Geen types\",\n    no_types_text: \"Maak uw eigen aangepaste gegevenstypen\",\n    no_issues: \"Er zijn geen problemen gedetecteerd.\",\n    strict_mode_is_on_no_issues:\n      \"Strikte modus is uitgeschakeld, dus er worden geen problemen weergegeven.\",\n    name: \"Naam\",\n    type: \"Type\",\n    null: \"Null\",\n    not_null: \"Niet null\",\n    nullable: \"Kan null zijn\",\n    primary: \"Primair\",\n    unique: \"Uniek\",\n    autoincrement: \"Automatisch ophogen\",\n    default_value: \"Standaardwaarde\",\n    check: \"Check-expressie\",\n    this_will_appear_as_is: \"*Dit zal ongewijzigd in het gegenereerde script verschijnen.\",\n    comment: \"Opmerking\",\n    add_field: \"Veld toevoegen\",\n    values: \"Waarden\",\n    size: \"Grootte\",\n    precision: \"Precisie\",\n    set_precision: \"Precisie instellen: 'grootte, decimalen'\",\n    use_for_batch_input: \"Gebruik , voor batchinvoer\",\n    indices: \"Indexen\",\n    add_index: \"Index toevoegen\",\n    select_fields: \"Velden selecteren\",\n    title: \"Titel\",\n    not_set: \"Niet ingesteld\",\n    foreign: \"Foreign\",\n    cardinality: \"Kardinaliteit\",\n    on_update: \"Bij update\",\n    on_delete: \"Bij verwijderen\",\n    swap: \"Wisselen\",\n    one_to_one: \"Eén op één\",\n    one_to_many: \"Eén op veel\",\n    many_to_one: \"Veel op één\",\n    content: \"Inhoud\",\n    types_info:\n      \"Deze functie is bedoeld voor object-relationele DBMS'en zoals PostgreSQL.\\nBij gebruik voor MySQL of MariaDB wordt een JSON-type gegenereerd met de bijbehorende json-validatiecontrole.\\nBij gebruik voor SQLite wordt het vertaald naar een BLOB.\\nBij gebruik voor MSSQL wordt een type-alias naar het eerste veld gegenereerd.\",\n    table_deleted: \"Tabel verwijderd\",\n    area_deleted: \"Gebied verwijderd\",\n    note_deleted: \"Notitie verwijderd\",\n    relationship_deleted: \"Relatie verwijderd\",\n    type_deleted: \"Type verwijderd\",\n    cannot_connect: \"Kan geen verbinding maken, de kolommen hebben verschillende typen\",\n    copied_to_clipboard: \"Gekopieerd naar klembord\",\n    create_new_diagram: \"Nieuw diagram maken\",\n    cancel: \"Annuleren\",\n    open_diagram: \"Diagram openen\",\n    rename_diagram: \"Diagram hernoemen\",\n    export: \"Exporteren\",\n    export_image: \"Afbeelding exporteren\",\n    create: \"Maken\",\n    confirm: \"Bevestigen\",\n    last_modified: \"Laatst gewijzigd\",\n    drag_and_drop_files: \"Sleep het bestand hierheen of klik om te uploaden.\",\n    upload_sql_to_generate_diagrams:\n      \"Upload een SQL-bestand om uw tabellen en kolommen automatisch te genereren.\",\n    overwrite_existing_diagram: \"Bestaand diagram overschrijven\",\n    only_mysql_supported:\n      \"*Voorlopig wordt alleen het laden van MySQL-scripts ondersteund.\",\n    blank: \"Leeg\",\n    filename: \"Bestandsnaam\",\n    table_w_no_name: \"Een tabel zonder naam gedeclareerd\",\n    duplicate_table_by_name: \"Dubbele tabel met de naam '{{tableName}}'\",\n    empty_field_name: \"Leeg veld `naam` in tabel '{{tableName}}'\",\n    empty_field_type: \"Leeg veld `type` in tabel '{{tableName}}'\",\n    no_values_for_field:\n      \"Veld '{{fieldName}}' van tabel '{{tableName}}' is van het type `{{type}}` maar er zijn geen waarden opgegeven\",\n    default_doesnt_match_type:\n      \"Standaardwaarde voor veld '{{fieldName}}' in tabel '{{tableName}}' komt niet overeen met het type\",\n    not_null_is_null:\n      \"Veld '{{fieldName}}' van tabel '{{tableName}}' is NOT NULL maar heeft standaard NULL\",\n    duplicate_fields:\n      \"Dubbele tabelvelden met de naam '{{fieldName}}' in tabel '{{tableName}}'\",\n    duplicate_index:\n      \"Dubbele index met de naam '{{indexName}}' in tabel '{{tableName}}'\",\n    empty_index: \"Index in tabel '{{tableName}}' indexeert geen kolommen\",\n    no_primary_key: \"Tabel '{{tableName}}' heeft geen primaire sleutel\",\n    type_with_no_name: \"Een type zonder naam gedeclareerd\",\n    duplicate_types: \"Dubbele types met de naam '{{typeName}}'\",\n    type_w_no_fields: \"Een leeg type '{{typeName}}' zonder velden gedeclareerd\",\n    empty_type_field_name: \"Leeg veld `naam` in type '{{typeName}}'\",\n    empty_type_field_type: \"Leeg veld `type` in type '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Veld '{{fieldName}}' van type '{{typeName}}' is van het type `{{type}}` maar er zijn geen waarden opgegeven\",\n    duplicate_type_fields:\n      \"Dubbele typevelden met de naam '{{fieldName}}' in type '{{typeName}}'\",\n    duplicate_reference: \"Dubbele referentie met de naam '{{refName}}'\",\n    circular_dependency: \"Circulaire afhankelijkheid met betrekking tot tabel '{{refName}}'\",\n    timeline: \"Tijdlijn\",\n    priority: \"Prioriteit\",\n    none: \"Geen\",\n    low: \"Laag\",\n    medium: \"Gemiddeld\",\n    high: \"Hoog\",\n    sort_by: \"Sorteren op\",\n    my_order: \"Mijn volgorde\",\n    completed: \"Voltooid\",\n    alphabetically: \"Alfabetisch\",\n    add_task: \"Taak toevoegen\",\n    details: \"Details\",\n    no_tasks: \"U heeft nog geen taken.\",\n    no_activity: \"U heeft nog geen activiteit.\",\n    move_element: \"Verplaats {{name}} naar {{coords}}\",\n    edit_area: \"{{extra}} Gebied {{areaName}} bewerken\",\n    delete_area: \"Gebied {{areaName}} verwijderen\",\n    edit_note: \"{{extra}} Notitie {{noteTitle}} bewerken\",\n    delete_note: \"Notitie {{noteTitle}} verwijderen\",\n    edit_table: \"{{extra}} Tabel {{tableName}} bewerken\",\n    delete_table: \"Tabel {{tableName}} verwijderen\",\n    edit_type: \"{{extra}} Type {{typeName}} bewerken\",\n    delete_type: \"Type {{typeName}} verwijderen\",\n    add_relationship: \"Relatie toevoegen\",\n    edit_relationship: \"{{extra}} Relatie {{refName}} bewerken\",\n    delete_relationship: \"Relatie {{refName}} verwijderen\",\n    not_found: \"Niet gevonden\",\n    pick_db: \"Kies een database\",\n    generic: \"Generiek\",\n    generic_description:\n      \"Generieke diagrammen kunnen naar elke SQL-variant worden geëxporteerd, maar ondersteunen weinig gegevenstypen.\",\n    enums: \"Enums\",\n    add_enum: \"Enum toevoegen\",\n    edit_enum: \"{{extra}} Enum {{enumName}} bewerken\",\n    delete_enum: \"Enum verwijderen\",\n    enum_w_no_name: \"Enum zonder naam gevonden\",\n    enum_w_no_values: \"Enum '{{enumName}}' zonder waarden gevonden\",\n    duplicate_enums: \"Dubbele enums met de naam '{{enumName}}'\",\n    no_enums: \"Geen enums\",\n    no_enums_text: \"Definieer hier enums\",\n    declare_array: \"Array declareren\",\n    empty_index_name: \"Een index zonder naam gedeclareerd in tabel '{{tableName}}'\",\n    didnt_find_diagram: \"Oeps! Het diagram niet gevonden.\",\n    unsigned: \"Unsigned\",\n    share: \"Delen\",\n    unshare: \"Delen stoppen\",\n    copy_link: \"Link kopiëren\",\n    readme: \"LEESMIJ\",\n    failed_to_load: \"Laden mislukt. Zorg ervoor dat de link correct is.\",\n    share_info:\n      \"* Het delen van deze link creëert geen live real-time samenwerkingssessie.\",\n    show_relationship_labels: \"Relatielabels tonen\",\n    docs: \"Documentatie\",\n    supported_types: \"Ondersteunde bestandstypen:\",\n    bulk_update: \"Bulk-update\",\n    multiselect: \"Meervoudige selectie\",\n    export_saved_data: \"Opgeslagen gegevens exporteren\",\n    dbml_view: \"DBML-weergave\",\n    tab_view: \"Tabbladweergave\",\n    label: \"Label\",\n    many_side_label: \"Veel (n) zijde label\",\n    version: \"Versie\",\n    versions: \"Versies\",\n    no_saved_versions: \"Geen opgeslagen versies\",\n    record_version: \"Versie vastleggen\",\n    commited_at: \"Vastgelegd op\",\n    read_only: \"Alleen-lezen\",\n    continue: \"Doorgaan\",\n    restore_version: \"Versie herstellen\",\n    restore_warning: \"Het laden van een andere versie zal alle wijzigingen overschrijven.\",\n    return_to_current: \"Terug naar diagram\",\n    no_changes_to_record: \"Geen wijzigingen om vast te leggen\",\n    click_to_view: \"Klik om te bekijken\",\n    load_more: \"Meer laden\",\n    clear_cache: \"Cache wissen\",\n    cache_cleared: \"Cache gewist\",\n    failed_to_record_version: \"Vastleggen van versie mislukt\",\n    failed_to_load_diagram: \"Laden van diagram mislukt\",\n    see_all: \"Alles zien\",\n  },\n};\n\nexport { nl, dutch };"
  },
  {
    "path": "src/i18n/locales/no.js",
    "content": "const norwegian = {\n  name: \"Norwegian\",\n  native_name: \"Norsk\",\n  code: \"no\",\n};\n\nconst no = {\n  translation: {\n    report_bug: \"Rapporter en feil\",\n    import_from: \"Importer\",\n    import: \"Importer\",\n    file: \"Fil\",\n    new: \"Ny\",\n    new_window: \"Nytt vindu\",\n    open: \"Åpne\",\n    save: \"Lagre\",\n    save_as: \"Lagre som\",\n    save_as_template: \"Lagre som mal\",\n    template_saved: \"Malen er lagret!\",\n    rename: \"Gi nytt navn\",\n    delete_diagram: \"Slett diagram\",\n    are_you_sure_delete_diagram:\n      \"Er du sikker på at du vil slette dette diagrammet? Denne handlingen er ugjenkallelig.\",\n    oops_smth_went_wrong: \"Oops! Noe gikk galt.\",\n    import_diagram: \"Importer diagram\",\n    import_from_source: \"Importer fra SQL\",\n    export_as: \"Eksporter som\",\n    export_source: \"Eksporter SQL\",\n    models: \"Modeller\",\n    exit: \"Avslutt\",\n    edit: \"Rediger\",\n    undo: \"Angre\",\n    redo: \"Gjør om\",\n    clear: \"Tøm\",\n    are_you_sure_clear:\n      \"Er du sikker på at du vil tømme diagrammet? Dette er ugjenkallelig.\",\n    cut: \"Klipp ut\",\n    copy: \"Kopier\",\n    paste: \"Lim inn\",\n    duplicate: \"Dupliser\",\n    delete: \"Slett\",\n    copy_as_image: \"Kopier som bilde\",\n    view: \"Vis\",\n    header: \"Menylinje\",\n    sidebar: \"Sidepanel\",\n    issues: \"Problemer\",\n    presentation_mode: \"Presentasjonsmodus\",\n    strict_mode: \"Streng modus\",\n    field_details: \"Feltdetaljer\",\n    reset_view: \"Tilbakestill visning\",\n    show_grid: \"Vis rutenett\",\n    show_cardinality: \"Vis kardinalitet\",\n    theme: \"Tema\",\n    light: \"Lys\",\n    dark: \"Mørk\",\n    zoom_in: \"Zoom inn\",\n    zoom_out: \"Zoom ut\",\n    fullscreen: \"Fullskjerm\",\n    settings: \"Innstillinger\",\n    show_timeline: \"Vis tidslinje\",\n    autosave: \"Automatisk lagring\",\n    panning: \"Panorering\",\n    show_debug_coordinates: \"Vis feilsøkingskoordinater\",\n    transform: \"Transformer\",\n    viewbox: \"Visningsboks\",\n    cursor_coordinates: \"Markørkoordinater\",\n    coordinate_space: \"Koordinatsystem\",\n    coordinate_space_screen: \"Skjerm\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Tabellbredde\",\n    language: \"Språk\",\n    flush_storage: \"Tøm lagring\",\n    are_you_sure_flush_storage:\n      \"Er du sikker på at du vil tømme lagringen? Dette vil ugjenkallelig slette alle dine diagrammer og egendefinerte maler.\",\n    storage_flushed: \"Lagring tømt\",\n    help: \"Hjelp\",\n    shortcuts: \"Snarveier\",\n    ask_on_discord: \"Spør oss på Discord\",\n    feedback: \"Tilbakemelding\",\n    no_changes: \"Ingen endringer\",\n    loading: \"Laster...\",\n    last_saved: \"Sist lagret\",\n    saving: \"Lagrer...\",\n    failed_to_save: \"Kunne ikke lagre\",\n    fit_window_reset: \"Tilpass vindu / Tilbakestill\",\n    zoom: \"Zoom\",\n    add_table: \"Legg til tabell\",\n    add_area: \"Legg til område\",\n    add_note: \"Legg til notat\",\n    add_type: \"Legg til type\",\n    to_do: \"Oppgaver\",\n    tables: \"Tabeller\",\n    relationships: \"Relasjoner\",\n    subject_areas: \"Emneområder\",\n    notes: \"Notater\",\n    types: \"Typer\",\n    search: \"Søk...\",\n    no_tables: \"Ingen tabeller\",\n    no_tables_text: \"Begynn å bygge diagrammet ditt!\",\n    no_relationships: \"Ingen relasjoner\",\n    no_relationships_text: \"Dra for å koble felter og danne relasjoner!\",\n    no_subject_areas: \"Ingen emneområder\",\n    no_subject_areas_text: \"Legg til emneområder for å gruppere tabeller!\",\n    no_notes: \"Ingen notater\",\n    no_notes_text: \"Bruk notater for å legge til ekstra informasjon\",\n    no_types: \"Ingen typer\",\n    no_types_text: \"Lag dine egne egendefinerte datatyper\",\n    no_issues: \"Ingen problemer ble oppdaget.\",\n    strict_mode_is_on_no_issues:\n      \"Streng modus er av, så ingen problemer vil bli vist.\",\n    name: \"Navn\",\n    type: \"Type\",\n    null: \"Null\",\n    not_null: \"Ikke null\",\n    primary: \"Primær\",\n    unique: \"Unik\",\n    autoincrement: \"Autoinkrement\",\n    default_value: \"Standardverdi\",\n    check: \"Sjekk uttrykk\",\n    this_will_appear_as_is:\n      \"*Dette vil vises i det genererte skriptet som det er.\",\n    comment: \"Kommentar\",\n    add_field: \"Legg til felt\",\n    values: \"Verdier\",\n    size: \"Størrelse\",\n    precision: \"Presisjon\",\n    set_precision: \"Sett presisjon: 'størrelse, siffer'\",\n    use_for_batch_input: \"Bruk , for batch-inndata\",\n    indices: \"Indekser\",\n    add_index: \"Legg til indeks\",\n    select_fields: \"Velg felter\",\n    title: \"Tittel\",\n    not_set: \"Ikke satt\",\n    foreign: \"Fremmed\",\n    cardinality: \"Kardinalitet\",\n    on_update: \"Ved oppdatering\",\n    on_delete: \"Ved sletting\",\n    swap: \"Bytt\",\n    one_to_one: \"En-til-en\",\n    one_to_many: \"En-til-mange\",\n    many_to_one: \"Mange-til-en\",\n    content: \"Innhold\",\n    types_info:\n      \"Denne funksjonen er ment for objekt-relasjonelle DBMS-er som PostgreSQL.\\nHvis brukt for MySQL eller MariaDB, vil en JSON-type bli generert med tilsvarende JSON-valideringssjekk.\\nHvis brukt for SQLite, vil det bli oversatt til en BLOB.\\nHvis brukt for MSSQL, vil en typealias til det første feltet bli generert.\",\n    table_deleted: \"Tabell slettet\",\n    area_deleted: \"Område slettet\",\n    note_deleted: \"Notat slettet\",\n    relationship_deleted: \"Relasjon slettet\",\n    type_deleted: \"Type slettet\",\n    cannot_connect: \"Kan ikke koble, kolonnene har forskjellige typer\",\n    copied_to_clipboard: \"Kopiert til utklippstavlen\",\n    create_new_diagram: \"Opprett nytt diagram\",\n    cancel: \"Avbryt\",\n    open_diagram: \"Åpne diagram\",\n    rename_diagram: \"Gi nytt navn til diagram\",\n    export: \"Eksporter\",\n    export_image: \"Eksporter bilde\",\n    create: \"Opprett\",\n    confirm: \"Bekreft\",\n    last_modified: \"Sist endret\",\n    drag_and_drop_files: \"Dra og slipp filen her eller klikk for å laste opp.\",\n    upload_sql_to_generate_diagrams:\n      \"Last opp en SQL-fil for å autogenerere dine tabeller og kolonner.\",\n    overwrite_existing_diagram: \"Overskriv eksisterende diagram\",\n    only_mysql_supported: \"*For tiden støttes kun lasting av MySQL-skript.\",\n    blank: \"Blank\",\n    filename: \"Filnavn\",\n    table_w_no_name: \"Deklarerte en tabell uten navn\",\n    duplicate_table_by_name: \"Duplikattabell med navnet '{{tableName}}'\",\n    empty_field_name: \"Tomt felt `navn` i tabell '{{tableName}}'\",\n    empty_field_type: \"Tomt felt `type` i tabell '{{tableName}}'\",\n    no_values_for_field:\n      \"'{{fieldName}}' feltet i tabellen '{{tableName}}' er av typen `{{type}}`, men ingen verdier er spesifisert\",\n    default_doesnt_match_type:\n      \"Standardverdien for feltet '{{fieldName}}' i tabellen '{{tableName}}' samsvarer ikke med dens type\",\n    not_null_is_null:\n      \"'{{fieldName}}' feltet i tabellen '{{tableName}}' er IKKE NULL, men har standardverdi NULL\",\n    duplicate_fields:\n      \"Duplikatfelter med navnet '{{fieldName}}' i tabell '{{tableName}}'\",\n    duplicate_index:\n      \"Duplikatindeks med navnet '{{indexName}}' i tabell '{{tableName}}'\",\n    empty_index: \"Indeks i tabell '{{tableName}}' indekserer ingen kolonner\",\n    no_primary_key: \"Tabellen '{{tableName}}' har ingen primærnøkkel\",\n    type_with_no_name: \"Deklarerte en type uten navn\",\n    duplicate_types: \"Duplikattyper med navnet '{{typeName}}'\",\n    type_w_no_fields: \"Deklarerte en tom type '{{typeName}}' uten felter\",\n    empty_type_field_name: \"Tomt felt `navn` i type '{{typeName}}'\",\n    empty_type_field_type: \"Tomt felt `type` i type '{{typeName}}'\",\n    no_values_for_type_field:\n      \"'{{fieldName}}' feltet i typen '{{typeName}}' er av typen `{{type}}`, men ingen verdier er spesifisert\",\n    duplicate_type_fields:\n      \"Duplikatfelter med navnet '{{fieldName}}' i type '{{typeName}}'\",\n    duplicate_reference: \"Duplikatreferanse med navnet '{{refName}}'\",\n    circular_dependency:\n      \"Sirkulær avhengighet som involverer tabell '{{refName}}'\",\n    timeline: \"Tidslinje\",\n    priority: \"Prioritet\",\n    none: \"Ingen\",\n    low: \"Lav\",\n    medium: \"Middels\",\n    high: \"Høy\",\n    sort_by: \"Sorter etter\",\n    my_order: \"Min rekkefølge\",\n    completed: \"Fullført\",\n    alphabetically: \"Alfabetisk\",\n    add_task: \"Legg til oppgave\",\n    details: \"Detaljer\",\n    no_tasks: \"Du har ingen oppgaver ennå.\",\n    no_activity: \"Du har ingen aktivitet ennå.\",\n    move_element: \"Flytt {{name}} til {{coords}}\",\n    edit_area: \"{{extra}} Rediger område {{areaName}}\",\n    delete_area: \"Slett område {{areaName}}\",\n    edit_note: \"{{extra}} Rediger notat {{noteTitle}}\",\n    delete_note: \"Slett notat {{noteTitle}}\",\n    edit_table: \"{{extra}} Rediger tabell {{tableName}}\",\n    delete_table: \"Slett tabell {{tableName}}\",\n    edit_type: \"{{extra}} Rediger type {{typeName}}\",\n    delete_type: \"Slett type {{typeName}}\",\n    add_relationship: \"Legg til relasjon\",\n    edit_relationship: \"{{extra}} Rediger relasjon {{refName}}\",\n    delete_relationship: \"Slett relasjon {{refName}}\",\n    not_found: \"Ikke funnet\",\n    pick_db: \"Velg en database\",\n    generic: \"Generisk\",\n    generic_description:\n      \"Generiske diagrammer kan eksporteres til alle SQL-varianter, men støtter få datatyper.\",\n    enums: \"Enum-er\",\n    add_enum: \"Legg til enum\",\n    edit_enum: \"{{extra}} Rediger enum {{enumName}}\",\n    delete_enum: \"Slett enum\",\n    enum_w_no_name: \"Fant enum uten navn\",\n    enum_w_no_values: \"Fant enum '{{enumName}}' uten verdier\",\n    duplicate_enums: \"Duplikat enum-er med navnet '{{enumName}}'\",\n    no_enums: \"Ingen enum-er\",\n    no_enums_text: \"Definer enum-er her\",\n    declare_array: \"Deklarer array\",\n    empty_index_name: \"Deklarerte en indeks uten navn i tabell '{{tableName}}'\",\n    didnt_find_diagram: \"Oops! Fant ikke diagrammet.\",\n    unsigned: \"Usignert\",\n    share: \"Del\",\n    copy_link: \"Kopier lenke\",\n    readme: \"README\",\n    failed_to_load: \"Kunne ikke laste. Forsikre deg om at lenken er korrekt.\",\n    share_info:\n      \"* Å dele denne lenken vil ikke opprette en live sanntidssamarbeidssession.\",\n  },\n};\n\nexport { no, norwegian };\n"
  },
  {
    "path": "src/i18n/locales/od.js",
    "content": "const odia = {\n  name: \"Odia\",\n  native_name: \"ଓଡିଆ\",\n  code: \"od\",\n};\n\nconst od = {\n  translation: {\n    report_bug: \"ବଗ୍ ରିପୋର୍ଟ କରନ୍ତୁ\",\n    import_from: \"ଆମଦାନି\",\n    import: \"ଆମଦାନି\",\n    file: \"ଫାଇଲ୍\",\n    new: \"ନୂତନ\",\n    new_window: \"ନୂତନ ୱିଣ୍ଡୋ\",\n    open: \"ଖୋଲନ୍ତୁ\",\n    save: \"ସେଭ୍\",\n    save_as: \"ସେଭ୍ ଭାବରେ\",\n    save_as_template: \"ଟେମ୍ପଲେଟ୍ ଭାବରେ ସେଭ୍ କରନ୍ତୁ\",\n    template_saved: \"ଟେମ୍ପଲେଟ୍ ସେଭ୍ ହୋଇଗଲା\",\n    rename: \"ନାମ ପରିବର୍ତ୍ତନ କରନ୍ତୁ\",\n    delete_diagram: \"ଡାୟାଗ୍ରାମ୍ ହଟାନ୍ତୁ\",\n    are_you_sure_delete_diagram: \"ଆପଣ ନିଶ୍ଚିତ ଏହି ଡାୟାଗ୍ରାମ୍ ହଟାଇବେ? \",\n    oops_smth_went_wrong: \"ଉଫ୍! କିଛି ଭୁଲ୍ ହୋଇଗଲା।\",\n    import_diagram: \"ଡାୟାଗ୍ରାମ୍ ଆମଦାନି କରନ୍ତୁ\",\n    import_from_source: \"SQL ରୁ ଆମଦାନି କରନ୍ତୁ\",\n    export_as: \"ରୂପେ ରପ୍ତାନି କରନ୍ତୁ\",\n    export_source: \"SQL ରପ୍ତାନି କରନ୍ତୁ\",\n    models: \"ମଡେଲ୍ସ\",\n    exit: \"ବାହାରିବା\",\n    edit: \"ସମ୍ପାଦନ କରନ୍ତୁ\",\n    undo: \"ପୂର୍ବବତ୍ କରନ୍ତୁ\",\n    redo: \"ପୁନରାବୃତ୍ତ କରନ୍ତୁ\",\n    clear: \"ସଫା କରନ୍ତୁ\",\n    are_you_sure_clear:\n      \"ଆପଣ ନିଶ୍ଚିତ ଏହି ଡାୟାଗ୍ରାମ୍ ସଫା କରିବେ? ଏହା ଅପରିବର୍ତ୍ତନୀୟ ଅଟେ।\",\n    cut: \"କଟ୍ କରନ୍ତୁ\",\n    copy: \"କପି କରନ୍ତୁ\",\n    paste: \"ପେଷ୍ଟ କରନ୍ତୁ\",\n    duplicate: \"ନକଲ୍ କରନ୍ତୁ\",\n    delete: \"ହଟାନ୍ତୁ\",\n    copy_as_image: \"ଛବି ଭାବରେ କପି କରନ୍ତୁ\",\n    view: \"ଦୃଶ୍ୟ\",\n    header: \"ମେନୁବାର୍\",\n    sidebar: \"ସାଇଡବାର୍\",\n    issues: \"ସମସ୍ୟାଗୁଡିକ\",\n    presentation_mode: \"ପ୍ରସ୍ତୁତି ମୋଡ୍\",\n    strict_mode: \"ସ୍ତ୍ରିକ୍ଟ ମୋଡ୍\",\n    field_details: \"ଫିଲ୍ଡ ବିବରଣୀ\",\n    reset_view: \"ଦୃଶ୍ୟ ପୁନଃସେଟ୍ କରନ୍ତୁ\",\n    show_grid: \"ଗ୍ରିଡ୍ ଦେଖାନ୍ତୁ\",\n    show_cardinality: \"କାର୍ଡିନାଲିଟି ଦେଖାନ୍ତୁ\",\n    theme: \"ଥିମ୍\",\n    light: \"ଆଲୋକ\",\n    dark: \"ଅନ୍ଧକାର\",\n    zoom_in: \"ଜୁମ୍ ଇନ୍\",\n    zoom_out: \"ଜୁମ୍ ଆଉଟ୍\",\n    fullscreen: \"ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ୍\",\n    settings: \"ସେଟିଂସ୍\",\n    show_timeline: \"ଟାଇମଲାଇନ୍ ଦେଖାନ୍ତୁ\",\n    autosave: \"ଅଟୋସେଭ୍\",\n    panning: \"ପ୍ୟାନିଂ\",\n    table_width: \"ଟେବଲ୍ ଚଉଡ଼ା\",\n    language: \"ଭାଷା\",\n    flush_storage: \"ସ୍ଟୋରେଜ୍ ସଫା କରନ୍ତୁ\",\n    are_you_sure_flush_storage:\n      \"ଆପଣ ନିଶ୍ଚିତ ସ୍ଟୋରେଜ୍ ସଫା କରିବେ? ଏହା ସମସ୍ତ ଆପଣଙ୍କର ଡାୟାଗ୍ରାମ୍ ଏବଂ କଷ୍ଟମ୍ ଟେମ୍ପଲେଟ୍ ଅପରିବର୍ତ୍ତନୀୟ ଭାବରେ ହଟାଇଦେବ।\",\n    storage_flushed: \"ସ୍ଟୋରେଜ୍ ସଫା ହୋଇଗଲା\",\n    help: \"ସାହାଯ୍ୟ\",\n    shortcuts: \"ଶର୍ଟକଟ୍ସ\",\n    ask_on_discord: \"ଆମକୁ Discord ରେ ପଚାରନ୍ତୁ\",\n    feedback: \"ଫିଡବ୍ୟାକ୍\",\n    no_changes: \"କୌଣସି ପରିବର୍ତ୍ତନ ନାହିଁ\",\n    loading: \"ଲୋଡ୍ ହେଉଛି...\",\n    last_saved: \"ଶେଷ ସେଭ୍\",\n    saving: \"ସେଭ୍ ହେଉଛି...\",\n    failed_to_save: \"ସେଭ୍ କରିବାରେ ବିଫଳ\",\n    fit_window_reset: \"ୱିଣ୍ଡୋ ଫିଟ୍ କରନ୍ତୁ / ପୁନଃସେଟ୍ କରନ୍ତୁ\",\n    zoom: \"ଜୁମ୍\",\n    add_table: \"ଟେବଲ୍ ଯୋଡନ୍ତୁ\",\n    add_area: \"ଅଞ୍ଚଳ ଯୋଡନ୍ତୁ\",\n    add_note: \"ଟିପ୍ପଣୀ ଯୋଡନ୍ତୁ\",\n    add_type: \"ପ୍ରକାର ଯୋଡନ୍ତୁ\",\n    to_do: \"କରିବାକୁ\",\n    tables: \"ଟେବଲ୍ସ\",\n    relationships: \"ସମ୍ପର୍କ\",\n    subject_areas: \"ବିଷୟ ଅଞ୍ଚଳଗୁଡିକ\",\n    notes: \"ଟିପ୍ପଣୀଗୁଡିକ\",\n    types: \"ପ୍ରକାରଗୁଡିକ\",\n    search: \"ଖୋଜନ୍ତୁ...\",\n    no_tables: \"କୌଣସି ଟେବଲ୍ ନାହିଁ\",\n    no_tables_text: \"ଆପଣଙ୍କର ଡାୟାଗ୍ରାମ୍ ତିଆରି କରିବା ଆରମ୍ଭ କରନ୍ତୁ!\",\n    no_relationships: \"କୌଣସି ସମ୍ପର୍କ ନାହିଁ\",\n    no_relationships_text:\n      \"ଫିଲ୍ଡଗୁଡିକୁ ଜୋଡିବାକୁ ଟାଣନ୍ତୁ ଏବଂ ସମ୍ପର୍କ ତିଆରି କରନ୍ତୁ!\",\n    no_subject_areas: \"କୌଣସି ବିଷୟ ଅଞ୍ଚଳ ନାହିଁ\",\n    no_subject_areas_text: \"ଗ୍ରୁପ୍ ଟେବଲ୍ଗୁଡିକୁ ବିଷୟ ଅଞ୍ଚଳ ଯୋଡନ୍ତୁ!\",\n    no_notes: \"କୌଣସି ଟିପ୍ପଣୀ ନାହିଁ\",\n    no_notes_text: \"ଅତିରିକ୍ତ ସୂଚନା ରେକର୍ଡ କରିବାକୁ ଟିପ୍ପଣୀଗୁଡିକୁ ବ୍ୟବହାର କରନ୍ତୁ\",\n    no_types: \"କୌଣସି ପ୍ରକାର ନାହିଁ\",\n    no_types_text: \"ଆପଣଙ୍କର ନିଜସ୍ୱ କଷ୍ଟମ୍ ଡାଟା ପ୍ରକାର ତିଆରି କରନ୍ତୁ\",\n    no_issues: \"କୌଣସି ସମସ୍ୟା ମିଳିଲା ନାହିଁ।\",\n    strict_mode_is_on_no_issues:\n      \"ସ୍ତ୍ରିକ୍ଟ ମୋଡ୍ ବନ୍ଦ ଅଟେ ତେଣୁ କୌଣସି ସମସ୍ୟା ଦେଖାଯିବ ନାହିଁ।\",\n    name: \"ନାମ\",\n    type: \"ପ୍ରକାର\",\n    null: \"Null\",\n    not_null: \"ନଟ୍ null\",\n    primary: \"ପ୍ରାଥମିକ\",\n    unique: \"ଅନନ୍ୟ\",\n    autoincrement: \"ସ୍ୱୟଂ ବୃଦ୍ଧି\",\n    default_value: \"ଡିଫଲ୍ଟ\",\n    check: \"ଚେକ୍ ଏକ୍ସପ୍ରେସନ୍\",\n    this_will_appear_as_is:\n      \"*ଏହା ଜେନେରେଟ୍ ସ୍କ୍ରିପ୍ଟରେ ଯେପରି ଅଛି ସେପରି ଦେଖାଯିବ।\",\n    comment: \"ଟିପ୍ପଣୀ\",\n    add_field: \"ଫିଲ୍ଡ ଯୋଡନ୍ତୁ\",\n    values: \"ମୂଲ୍ୟଗୁଡିକ\",\n    size: \"ଆକାର\",\n    precision: \"ସଠିକତା\",\n    set_precision: \"ସଠିକତା ସେଟ୍ କରନ୍ତୁ: (ଆକାର, ଡିଜିଟ୍ସ)\",\n    use_for_batch_input: \"ବ୍ୟାଚ୍ ଇନପୁଟ୍ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ\",\n    indices: \"ଇଣ୍ଡାଇସେସ୍\",\n    add_index: \"ଇଣ୍ଡେକ୍ସ ଯୋଡନ୍ତୁ\",\n    select_fields: \"ଫିଲ୍ଡଗୁଡିକୁ ଚୟନ କରନ୍ତୁ\",\n    title: \"ଶୀର୍ଷକ\",\n    not_set: \"ସେଟ୍ ହୋଇନାହିଁ\",\n    foreign: \"ଫରେନ୍\",\n    cardinality: \"କାର୍ଡିନାଲିଟି\",\n    on_update: \"ଅଦ୍ୟତନରେ\",\n    on_delete: \"ହଟାଇବାରେ\",\n    swap: \"ସ୍ୱାପ୍\",\n    one_to_one: \"ଏକରୁ ଏକ\",\n    one_to_many: \"ଏକରୁ ଅନେକ\",\n    many_to_one: \"ଅନେକରୁ ଏକ\",\n    content: \"ବିଷୟବସ୍ତୁ\",\n    types_info:\n      \"ଏହି ସୁବିଧା object-relational DBMS ଯେପରିକି PostgreSQL ପାଇଁ ଅଟେ।\\nଯଦି MySQL କିମ୍ବା MariaDB ପାଇଁ ବ୍ୟବହାର କରାଯାଏ, ତେବେ ଏକ JSON ପ୍ରକାର ଜେନେରେଟ୍ ହେବ ଯାହାରେ ସମ୍ବନ୍ଧିତ json ବୈଧତା ଯାଞ୍ଚ ହେବ।\\nଯଦି SQLite ପାଇଁ ବ୍ୟବହାର କରାଯାଏ ତେବେ ଏହାକୁ BLOB ରେ ପରିବର୍ତ୍ତନ କରାଯିବ।\\nଯଦି MSSQL ପାଇଁ ବ୍ୟବହାର କରାଯାଏ ତେବେ ପ୍ରଥମ ଫିଲ୍ଡ ପାଇଁ ଏକ ପ୍ରକାର ଉପନାମ ଜେନେରେଟ୍ ହେବ।\",\n    table_deleted: \"ଟେବଲ୍ ହଟାଇ ଦିଆଗଲା\",\n    area_deleted: \"ଅଞ୍ଚଳ ହଟାଇ ଦିଆଗଲା\",\n    note_deleted: \"ଟିପ୍ପଣୀ ହଟାଇ ଦିଆଗଲା\",\n    relationship_deleted: \"ସମ୍ପର୍କ ହଟାଇ ଦିଆଗଲା\",\n    type_deleted: \"ପ୍ରକାର ହଟାଇ ଦିଆଗଲା\",\n    cannot_connect: \"କନେକ୍ଟ୍ କରିପାରିବେ ନାହିଁ, କଲମ୍ ପ୍ରକାର ଭିନ୍ନ ଅଟେ\",\n    copied_to_clipboard: \"କ୍ଲିପ୍ବୋର୍ଡକୁ କପି ହୋଇଗଲା\",\n    create_new_diagram: \"ନୂତନ ଡାୟାଗ୍ରାମ୍ ତିଆରି କରନ୍ତୁ\",\n    cancel: \"ବାତିଲ୍ କରନ୍ତୁ\",\n    open_diagram: \"ଡାୟାଗ୍ରାମ୍ ଖୋଲନ୍ତୁ\",\n    rename_diagram: \"ଡାୟାଗ୍ରାମ୍ ନାମ ପରିବର୍ତ୍ତନ କରନ୍ତୁ\",\n    export: \"ରପ୍ତାନି\",\n    export_image: \"ଛବି ରପ୍ତାନି\",\n    create: \"ତିଆରି କରନ୍ତୁ\",\n    confirm: \"ନିଶ୍ଚିତ କରନ୍ତୁ\",\n    last_modified: \"ଶେଷ ସମୟରେ ସଂଶୋଧିତ\",\n    drag_and_drop_files:\n      \"ଫାଇଲ୍କୁ ଏଠାରେ ଟାଣନ୍ତୁ ଏବଂ ଛାଡନ୍ତୁ କିମ୍ବା ଅପଲୋଡ୍ କରିବାକୁ କ୍ଲିକ୍ କରନ୍ତୁ।\",\n    upload_sql_to_generate_diagrams:\n      \"ଆପଣଙ୍କର ଟେବଲ୍ ଏବଂ କଲମ୍ଗୁଡିକୁ ସ୍ୱୟଂଚାଳିତ ଭାବରେ ଜେନେରେଟ୍ କରିବାକୁ ଏକ sql ଫାଇଲ୍ ଅପଲୋଡ୍ କରନ୍ତୁ।\",\n    overwrite_existing_diagram: \"ବର୍ତ୍ତମାନର ଡାୟାଗ୍ରାମ୍କୁ ଅଧିଲେଖନ କରନ୍ତୁ\",\n    only_mysql_supported:\n      \"*ବର୍ତ୍ତମାନ କେବଳ MySQL ସ୍କ୍ରିପ୍ଟଗୁଡିକୁ ଲୋଡ୍ କରିବା ସମର୍ଥିତ।\",\n    blank: \"ଖାଲି\",\n    filename: \"ଫାଇଲ୍ନାମ୍\",\n    table_w_no_name: \"ନାମ ବିନା ଟେବଲ୍ ଘୋଷଣା କରାଯାଇଛି\",\n    duplicate_table_by_name: \"ନାମ ଦ୍ୱାରା ନକଲ୍ ଟେବଲ୍ '{{tableName}}'\",\n    empty_field_name: \"ଟେବଲ୍ '{{tableName}}' ରେ ଖାଲି ଫିଲ୍ଡ `ନାମ`\",\n    empty_field_type: \"ଟେବଲ୍ '{{tableName}}' ରେ ଖାଲ\",\n    no_values_for_field:\n      \"ଟେବଲ '{{tableName}}' ର ଫିଲ୍ଡ '{{fieldName}}' ର ପ୍ରକାର `{{type}}` ଅଛି କିନ୍ତୁ କୌଣସି ମୂଲ୍ୟ ନିର୍ଦ୍ଦିଷ୍ଟ ହୋଇନାହିଁ\",\n    default_doesnt_match_type:\n      \"ଟେବଲ '{{tableName}}' ରେ ଫିଲ୍ଡ '{{fieldName}}' ର ଡିଫଲ୍ଟ ମୂଲ୍ୟ ତାହାର ପ୍ରକାର ସହିତ ମେଳ ଖାଉନାହିଁ\",\n    not_null_is_null:\n      \"ଟେବଲ '{{tableName}}' ର ଫିଲ୍ଡ '{{fieldName}}' ର ମୂଲ୍ୟ NOT NULL ଅଛି କିନ୍ତୁ ଡିଫଲ୍ଟ NULL ଅଛି\",\n    duplicate_fields:\n      \"ଟେବଲ '{{tableName}}' ରେ ନାମ '{{fieldName}}' ଥିବା ଡୁପ୍ଲିକେଟ ଟେବଲ ଫିଲ୍ଡସ୍\",\n    duplicate_index:\n      \"ଟେବଲ '{{tableName}}' ରେ ନାମ '{{indexName}}' ଥିବା ଡୁପ୍ଲିକେଟ ଇଣ୍ଡେକ୍ସ\",\n    empty_index:\n      \"ଟେବଲ '{{tableName}}' ରେ ଇଣ୍ଡେକ୍ସ କୌଣସି କଲମ୍ ଇଣ୍ଡେକ୍ସ କରୁନାହିଁ\",\n    no_primary_key: \"ଟେବଲ '{{tableName}}' ରେ କୌଣସି ପ୍ରାଥମିକ କୁଞ୍ଜି ନାହିଁ\",\n    type_with_no_name: \"କୌଣସି ନାମ ନଥିବା ପ୍ରକାରକୁ ଘୋଷଣା କରାଯାଇଛି\",\n    duplicate_types: \"ନାମ '{{typeName}}' ଥିବା ଡୁପ୍ଲିକେଟ ପ୍ରକାର\",\n    type_w_no_fields:\n      \"କୌଣସି ଫିଲ୍ଡସ୍ ନଥିବା ପ୍ରକାର '{{typeName}}' କୁ ଘୋଷଣା କରାଯାଇଛି\",\n    empty_type_field_name: \"ପ୍ରକାର '{{typeName}}' ରେ ଖାଲି ଫିଲ୍ଡ `ନାମ`\",\n    empty_type_field_type: \"ପ୍ରକାର '{{typeName}}' ରେ ଖାଲି ଫିଲ୍ଡ `ପ୍ରକାର`\",\n    no_values_for_type_field:\n      \"ପ୍ରକାର '{{typeName}}' ର ଫିଲ୍ଡ '{{fieldName}}' ର ପ୍ରକାର `{{type}}` ଅଛି କିନ୍ତୁ କୌଣସି ମୂଲ୍ୟ ନିର୍ଦ୍ଦିଷ୍ଟ ହୋଇନାହିଁ\",\n    duplicate_type_fields:\n      \"ପ୍ରକାର '{{typeName}}' ରେ ନାମ '{{fieldName}}' ଥିବା ଡୁପ୍ଲିକେଟ ପ୍ରକାର ଫିଲ୍ଡସ୍\",\n    duplicate_reference: \"ନାମ '{{refName}}' ଥିବା ଡୁପ୍ଲିକେଟ ସନ୍ଦର୍ଭ\",\n    circular_dependency: \"ଟେବଲ '{{refName}}' ରେ ପରିପତ୍ର ନିର୍ଭରତା\",\n    timeline: \"ସମୟରେଖା\",\n    priority: \"ପ୍ରାଥମିକତା\",\n    none: \"କିଛି ନାହିଁ\",\n    low: \"ନିମ୍ନ\",\n    medium: \"ମଧ୍ୟମ\",\n    high: \"ଉଚ୍ଚ\",\n    sort_by: \"ଦ୍ୱାରା କ୍ରମବଦ୍ଧ କରନ୍ତୁ\",\n    my_order: \"ମୋର କ୍ରମ\",\n    completed: \"ସମ୍ପୂର୍ଣ୍ଣ\",\n    alphabetically: \"ବର୍ଣ୍ଣାନୁକ୍ରମରେ\",\n    add_task: \"କାର୍ଯ୍ୟ ଯୋଡନ୍ତୁ\",\n    details: \"ବିବରଣୀ\",\n    no_tasks: \"ଆପଣଙ୍କ ପାଖରେ ଏପର୍ଯ୍ୟନ୍ତ କୌଣସି କାର୍ଯ୍ୟ ନାହିଁ।\",\n    no_activity: \"ଆପଣଙ୍କ ପାଖରେ ଏପର୍ଯ୍ୟନ୍ତ କୌଣସି କାର୍ଯ୍ୟକଳାପ ନାହିଁ।\",\n    move_element: \"{{name}} କୁ {{coords}} ରେ ନେଇଯାନ୍ତୁ\",\n    edit_area: \"{{extra}} ଏଡିଟ୍ ଏରିଆ {{areaName}}\",\n    delete_area: \"ଏରିଆ {{areaName}} କୁ ହଟାନ୍ତୁ\",\n    edit_note: \"{{extra}} ନୋଟ୍ ଏଡିଟ୍ କରନ୍ତୁ {{noteTitle}}\",\n    delete_note: \"ନୋଟ୍ {{noteTitle}} କୁ ହଟାନ୍ତୁ\",\n    edit_table: \"{{extra}} ଟେବଲ ଏଡିଟ୍ କରନ୍ତୁ {{tableName}}\",\n    delete_table: \"ଟେବଲ {{tableName}} କୁ ହଟାନ୍ତୁ\",\n    edit_type: \"{{extra}} ପ୍ରକାର ଏଡିଟ୍ କରନ୍ତୁ {{typeName}}\",\n    delete_type: \"ପ୍ରକାର {{typeName}} କୁ ହଟାନ୍ତୁ\",\n    add_relationship: \"ସମ୍ପର୍କ ଯୋଡନ୍ତୁ\",\n    edit_relationship: \"{{extra}} ସମ୍ପର୍କ ଏଡିଟ୍ କରନ୍ତୁ {{refName}}\",\n    delete_relationship: \"ସମ୍ପର୍କ {{refName}} କୁ ହଟାନ୍ତୁ\",\n    not_found: \"ମିଳିଲା ନାହିଁ\",\n  },\n};\n\nexport { od, odia };\n"
  },
  {
    "path": "src/i18n/locales/pa-pk.js",
    "content": "const punjabipk = {\n  name: \"Punjabi\",\n  native_name: \"پنجابی\",\n  code: \"pa-PK\",\n};\n\nconst pa_pk = {\n  translation: {\n    report_bug: \"مسئلہ رپورٹ کرو\",\n    import: \"منگاؤ\",\n    inherits: \"وراثت\",\n    merging_column_w_inherited_definition:\n      \"ٹیبل '{{tableName}}' وچ کالم '{{fieldName}}' وراثت دی تعریف نال رلا دتا جاوے گا\",\n    import_from: \"توں منگاؤ\",\n    file: \"فائل\",\n    new: \"نواں\",\n    new_window: \"نواں ونڈو\",\n    no_saved_diagrams: \"تہاڈے کول کوئی محفوظ ڈایاگرام نہیں\",\n    open: \"کھولو\",\n    open_recent: \"حالیہ کھولو\",\n    save: \"محفوظ کرو\",\n    save_as: \"ایس طرح محفوظ کرو\",\n    save_as_template: \"ٹیمپلیٹ وج محفوظ کرو\",\n    template_saved: \"ٹیمپلیٹ محفوظ ہو گیا!\",\n    rename: \"نواں ناں رکھو\",\n    delete_diagram: \"ڈایاگرام مکاؤ\",\n    are_you_sure_delete_diagram:\n      \"تُسی پکا ایہہ ڈایاگرام مٹانا چاہندے او؟ ایہہ کم واپس نہیں ہو سکدا۔\",\n    oops_smth_went_wrong: \"اوہ! کج غلط ہو گیا۔\",\n    import_diagram: \"ڈایاگرام منگاؤ\",\n    import_from_source: \"سورس توں منگاؤ\",\n    export_as: \"ایس طرح برآمد کرو\",\n    export_source: \"سورس برآمد کرو\",\n    models: \"ماڈل\",\n    exit: \"باہر نکلو\",\n    edit: \"ترمیم کرو\",\n    undo: \"واپس کرو\",\n    redo: \"دوبارہ کرو\",\n    clear: \"صاف کرو\",\n    are_you_sure_clear:\n      \"تُسی پکا ایہہ ڈایاگرام صاف کرنا چاہندے او؟ ایہہ واپس نہیں ہو سکدا۔\",\n    cut: \"کٹ کرو\",\n    copy: \"کاپی کرو\",\n    paste: \"چپکاؤ\",\n    duplicate: \"ڈپلیکیٹ کرو\",\n    delete: \"مکاؤ\",\n    copy_as_image: \"تصویر بنا کے کاپی کرو\",\n    view: \"ویکھو\",\n    header: \"ہیڈر\",\n    sidebar: \"سائیڈبار\",\n    issues: \"مسئلے\",\n    presentation_mode: \"پیشکاری موڈ\",\n    strict_mode: \"سخت موڈ\",\n    field_details: \"فیلڈ دیاں تفصیل\",\n    reset_view: \"ویکھن دا انداز ری سیٹ کرو\",\n    show_grid: \"گرڈ وکھاؤ\",\n    snap_to_grid: \"گرڈ نال جوڑو\",\n    show_datatype: \"ڈیٹا دی قسم وکھاؤ\",\n    show_cardinality: \"کارڈینلٹی وکھاؤ\",\n    theme: \"تھیم\",\n    light: \"روشن\",\n    dark: \"ہنیرلا\",\n    zoom_in: \"زوم ان کرو\",\n    zoom_out: \"زوم آؤٹ کرو\",\n    fullscreen: \"پوری سکرین\",\n    settings: \"سیٹنگاں\",\n    show_timeline: \"ٹائم لائن وکھاؤ\",\n    autosave: \"آٹو سیو\",\n    panning: \"پیننگ\",\n    show_debug_coordinates: \"ڈیبگ کوآرڈینیٹس وکھاؤ\",\n    transform: \"تبدیل کرو\",\n    viewbox: \"ویو باکس\",\n    cursor_coordinates: \"کرسر کوآرڈینیٹس\",\n    coordinate_space: \"جگہ\",\n    coordinate_space_screen: \"سکرین\",\n    coordinate_space_diagram: \"ڈایاگرام\",\n    table_width: \"ٹیبل دی چوڑائی\",\n    language: \"زبان\",\n    flush_storage: \"سٹوریج صاف کرو\",\n    are_you_sure_flush_storage:\n      \"تُسی پکا سٹوریج صاف کرنا چاہندے او؟ ایہہ تہاڈے سارے ڈایاگرام تے کسٹم ٹیمپلیٹ ہمیشہ لئی مٹا دے گا۔\",\n    storage_flushed: \"سٹوریج صاف ہو گیا\",\n    help: \"مدد\",\n    shortcuts: \"شارٹ کٹ\",\n    ask_on_discord: \"Discord تے پچھو\",\n    feedback: \"فیڈبیک\",\n    no_changes: \"کوئی تبدیلی نہیں\",\n    loading: \"لوڈ ہو رہیا اے...\",\n    last_saved: \"آخری واری محفوظ کیتا\",\n    saving: \"محفوظ ہو رہیا اے...\",\n    failed_to_save: \"محفوظ نہیں ہویا\",\n    fit_window_reset: \"ونڈو دے مطابق کرو / ری سیٹ کرو\",\n    zoom: \"زوم\",\n    add_table: \"ٹیبل شامل کرو\",\n    add_area: \"ایریا شامل کرو\",\n    add_note: \"نوٹ شامل کرو\",\n    add_type: \"قسم شامل کرو\",\n    to_do: \"کرنا اے\",\n    tables: \"ٹیبلز\",\n    relationships: \"رشتے\",\n    subject_areas: \"موضوع والے علاقے\",\n    notes: \"نوٹس\",\n    types: \"اقسام\",\n    search: \"لبھو...\",\n    no_tables: \"کوئی ٹیبل نہیں\",\n    no_tables_text: \"اپنا ڈایاگرام بنانا شروع کرو!\",\n    no_relationships: \"کوئی رشتہ نہیں\",\n    no_relationships_text: \"رشتے بنانے لئی فیلڈز نوں جوڑو!\",\n    no_subject_areas: \"کوئی موضوع والا علاقہ نہیں\",\n    no_subject_areas_text: \"ٹیبلز نوں گروپ کرو تے موضوع والے علاقے شامل کرو!\",\n    no_notes: \"کوئی نوٹ نہیں\",\n    no_notes_text: \"وڈی معلومات لکھن لئی نوٹ استعمال کرو\",\n    no_types: \"کوئی قسم نہیں\",\n    no_types_text: \"اپنی کسٹم ڈیٹا دیاں اقسام بناؤ\",\n    no_issues: \"کوئی مسئلہ نہیں لبیا\",\n    strict_mode_is_on_no_issues:\n      \"سخت موڈ بند اے اس لئی کوئی مسئلے نہیں وکھائے جا رہے۔\",\n    name: \"ناں\",\n    type: \"قسم\",\n    null: \"نل\",\n    not_null: \"نل نہیں\",\n    nullable: \"نل ہو سکدا اے\",\n    primary: \"پرائمری\",\n    unique: \"یونیک\",\n    autoincrement: \"آپے ودھدا\",\n    default_value: \"پہلاں توں رکھی ویلیو\",\n    check: \"چیک ایکسپریشن\",\n    this_will_appear_as_is: \"*ایہہ اسکرپٹ وچ جیویں اے اویں ای نظر آوے گا۔\",\n    comment: \"کمنٹ\",\n    add_field: \"فیلڈ شامل کرو\",\n    values: \"ویلیوز\",\n    size: \"سائز\",\n    precision: \"درستگی\",\n    set_precision: \"درستگی سیٹ کرو: (سائز، عدد)\",\n    use_for_batch_input: \"بیچ ان پٹ لئی استعمال کرو\",\n    indices: \"اشاریے\",\n    add_index: \"انڈیکس شامل کرو\",\n    select_fields: \"فیلڈز چنو\",\n    title: \"عنوان\",\n    not_set: \"سیٹ نہیں ہویا\",\n    foreign: \"غیر ملکی\",\n    cardinality: \"کارڈینلٹی\",\n    on_update: \"اپڈیٹ تے\",\n    on_delete: \"مٹاؤن تے\",\n    swap: \"تبادلہ کرو\",\n    one_to_one: \"اک توں اک\",\n    one_to_many: \"اک توں کئی\",\n    many_to_one: \"کئی توں اک\",\n    content: \"مواد\",\n    types_info:\n      \"ایہہ فیچر آبجیکٹ-ریلیشنل DBMSs جیویں PostgreSQL لئی اے۔\\nاگر MySQL یا MariaDB لئی ورتیا جاوے تاں JSON قسم بنائی جاوے گی نالے json توثیق چیک وی ہووے گا۔\\nاگر SQLite لئی ورتیا جاوے تاں ایہہ BLOB وچ ترجمہ ہووے گا۔\\nاگر MSSQL لئی ورتیا جاوے تاں پہلے فیلڈ لئی ٹائپ عرف بنایا جاوے گا۔\",\n    table_deleted: \"ٹیبل مٹا دتا گیا\",\n    area_deleted: \"ایریا مٹا دتا گیا\",\n    note_deleted: \"نوٹ مٹا دتا گیا\",\n    relationship_deleted: \"تعلق مٹا دتا گیا\",\n    type_deleted: \"قسم مٹا دتی گئی\",\n    cannot_connect: \"جوڑ نہیں سکدا، کالم وکھری قسماں دے نیں\",\n    copied_to_clipboard: \"کلپ بورڈ تے کاپی ہو گیا\",\n    create_new_diagram: \"نواں ڈایاگرام بناؤ\",\n    cancel: \"منسوخ کرو\",\n    open_diagram: \"ڈایاگرام کھولو\",\n    rename_diagram: \"ڈایاگرام دا ناں بدلو\",\n    export: \"برآمد کرو\",\n    export_image: \"تصویر برآمد کرو\",\n    create: \"بناؤ\",\n    confirm: \"پکا کرو\",\n    last_modified: \"آخری واری بدلیا\",\n    drag_and_drop_files: \"فائل ایتھے سٹ دیو یا اپ لوڈ کرن لئی کلک کرو۔\",\n    upload_sql_to_generate_diagrams:\n      \"اپنے ٹیبل تے کالم آپے بناون لئی sql فائل اپ لوڈ کرو۔\",\n    overwrite_existing_diagram: \"موجودہ ڈایاگرام دے اتے لکھو\",\n    only_mysql_supported: \"*فی الحال صرف MySQL اسکرپٹس لوڈ کرن دی سہولت اے۔\",\n    blank: \"خالی\",\n    filename: \"فائل دا ناں\",\n    table_w_no_name: \"بغیر ناں دے ٹیبل دا اعلان کیتا\",\n    duplicate_table_by_name: \"'{{tableName}}' ناں نال ڈپلیکیٹ ٹیبل\",\n    empty_field_name: \"ٹیبل '{{tableName}}' وچ خالی فیلڈ `name`\",\n    empty_field_type: \"ٹیبل '{{tableName}}' وچ خالی فیلڈ `type`\",\n    no_values_for_field:\n      \"'{{tableName}}' ٹیبل دا فیلڈ '{{fieldName}}' `{{type}}` قسم دا اے پر کوئی ویلیو نہیں دتی گئی\",\n    default_doesnt_match_type:\n      \"ٹیبل '{{tableName}}' وچ فیلڈ '{{fieldName}}' دی ڈیفالٹ ویلیو اس دی قسم نال نہیں ملدی\",\n    not_null_is_null:\n      \"ٹیبل '{{tableName}}' دا فیلڈ '{{fieldName}}' NOT NULL اے پر اس دا ڈیفالٹ NULL اے\",\n    duplicate_fields:\n      \"ٹیبل '{{tableName}}' وچ '{{fieldName}}' ناں نال ڈپلیکیٹ فیلڈز\",\n    duplicate_index:\n      \"ٹیبل '{{tableName}}' وچ '{{indexName}}' ناں نال ڈپلیکیٹ انڈیکس\",\n    empty_index: \"ٹیبل '{{tableName}}' وچ انڈیکس کسے کالم نوں انڈیکس نہیں کردا\",\n    no_primary_key: \"ٹیبل '{{tableName}}' دی کوئی پرائمری کی نہیں اے\",\n    type_with_no_name: \"بغیر ناں دے قسم دا اعلان کیتا\",\n    duplicate_types: \"'{{typeName}}' ناں نال ڈپلیکیٹ قسماں\",\n    type_w_no_fields: \"بغیر فیلڈز دے خالی قسم '{{typeName}}' دا اعلان کیتا\",\n    empty_type_field_name: \"قسم '{{typeName}}' وچ خالی فیلڈ `name`\",\n    empty_type_field_type: \"قسم '{{typeName}}' وچ خالی فیلڈ `type`\",\n    no_values_for_type_field:\n      \"قسم '{{typeName}}' دا فیلڈ '{{fieldName}}' `{{type}}` قسم دا اے پر کوئی ویلیو نہیں دتی گئی\",\n    duplicate_type_fields:\n      \"قسم '{{typeName}}' وچ '{{fieldName}}' ناں نال ڈپلیکیٹ ٹائپ فیلڈز\",\n    duplicate_reference: \"'{{refName}}' ناں نال ڈپلیکیٹ حوالہ\",\n    circular_dependency: \"ٹیبل '{{refName}}' وچ گول انحصار\",\n    timeline: \"ٹائم لائن\",\n    priority: \"اہمیت\",\n    none: \"کچھ نہیں\",\n    low: \"ہلکی\",\n    medium: \"درمیانی\",\n    high: \"وڈی\",\n    sort_by: \"اس حساب نال ترتیب دو\",\n    my_order: \"میری ترتیب\",\n    completed: \"مکمل ہویا\",\n    alphabetically: \"حروف وار\",\n    add_task: \"کم شامل کرو\",\n    details: \"تفصیل\",\n    no_tasks: \"تہاڈے کول ہن تک کوئی کم نہیں۔\",\n    no_activity: \"تہاڈی ہن تک کوئی سرگرمی نہیں۔\",\n    move_element: \"{{name}} نوں {{coords}} تے منتقل کرو\",\n    edit_area: \"{{extra}} ایریا {{areaName}} ترمیم کرو\",\n    delete_area: \"ایریا {{areaName}} مٹاؤ\",\n    edit_note: \"{{extra}} نوٹ {{noteTitle}} ترمیم کرو\",\n    delete_note: \"نوٹ {{noteTitle}} مٹاؤ\",\n    edit_table: \"{{extra}} ٹیبل {{tableName}} ترمیم کرو\",\n    delete_table: \"ٹیبل {{tableName}} مٹاؤ\",\n    edit_type: \"{{extra}} قسم {{typeName}} ترمیم کرو\",\n    delete_type: \"قسم {{typeName}} مٹاؤ\",\n    add_relationship: \"تعلق شامل کرو\",\n    edit_relationship: \"{{extra}} تعلق {{refName}} ترمیم کرو\",\n    delete_relationship: \"تعلق {{refName}} مٹاؤ\",\n    not_found: \"نہیں لبیا\",\n    pick_db: \"ڈیٹا بیس چنو\",\n    generic: \"عام\",\n    generic_description:\n      \"عام ڈایاگرام کسے وی SQL ذائقے وچ برآمد کیتے جا سکدے نیں پر کچھ ڈیٹا دی قسماں دی حمایت کردے نیں۔\",\n    enums: \"Enums\",\n    add_enum: \"Enum شامل کرو\",\n    edit_enum: \"{{extra}} Enum {{enumName}} ترمیم کرو\",\n    delete_enum: \"Enum مٹاؤ\",\n    enum_w_no_name: \"بغیر ناں دے Enum لبیا\",\n    enum_w_no_values: \"Enum '{{enumName}}' بغیر ویلیوز دے لبیا\",\n    duplicate_enums: \"'{{enumName}}' ناں نال ڈپلیکیٹ Enums\",\n    enum_deleted: \"Enum مٹا دتا گیا\",\n    no_enums: \"کوئی Enums نہیں\",\n    no_enums_text: \"ایتھے Enums دی وضاحت کرو\",\n    declare_array: \"Array دا اعلان کرو\",\n    empty_index_name:\n      \"ٹیبل '{{tableName}}' وچ بغیر ناں دے انڈیکس دا اعلان کیتا\",\n    didnt_find_diagram: \"اوہ! ڈایاگرام نہیں لبیا۔\",\n    unsigned: \"Unsigned\",\n    share: \"شیئر کرو\",\n    unshare: \"شیئر ختم کرو\",\n    copy_link: \"لنک کاپی کرو\",\n    readme: \"README\",\n    failed_to_load: \"لوڈ کرن وچ ناکام۔ یقینی بناؤ کہ لنک درست اے۔\",\n    share_info:\n      \"* اس لنک نوں شیئر کرن نال لائیو ریئل ٹائم تعاون دا سیشن نہیں بنے گا۔\",\n    show_relationship_labels: \"تعلقات دے لیبل وکھاؤ\",\n    docs: \"دستاویزات\",\n    supported_types: \"سپورٹڈ فائل قسماں:\",\n    bulk_update: \"بلک اپ ڈیٹ\",\n    multiselect: \"ملٹی سلیکٹ\",\n    export_saved_data: \"محفوظ کیتا ڈیٹا برآمد کرو\",\n    dbml_view: \"DBML ویو\",\n    tab_view: \"ٹیب ویو\",\n    label: \"لیبل\",\n    many_side_label: \"Many(n) سائیڈ لیبل\",\n    version: \"ورژن\",\n    versions: \"ورژنز\",\n    no_saved_versions: \"کوئی محفوظ ورژن نہیں\",\n    record_version: \"ورژن ریکارڈ کرو\",\n    commited_at: \"تے کمٹ کیتا گیا\",\n    read_only: \"صرف پڑھن لئی\",\n    continue: \"جاری رکھو\",\n    restore_version: \"ورژن بحال کرو\",\n    restore_warning:\n      \"دوجا ورژن لوڈ کرن نال کوئی وی تبدیلیاں اوور رائٹ ہو جان گیاں۔\",\n    return_to_current: \"ڈایاگرام تے واپس جاؤ\",\n    no_changes_to_record: \"ریکارڈ کرن لئی کوئی تبدیلیاں نہیں\",\n    click_to_view: \"ویکھن لئی کلک کرو\",\n    load_more: \"ہور لوڈ کرو\",\n    clear_cache: \"کیشے صاف کرو\",\n    cache_cleared: \"کیشے صاف کر دتا گیا\",\n    failed_to_record_version: \"ورژن ریکارڈ کرن وچ ناکام\",\n    failed_to_load_diagram: \"ڈایاگرام لوڈ کرن وچ ناکام\",\n    see_all: \"سارے ویکھو\",\n    insert_sql: \"SQL داخل کرو\",\n    upload_file: \"فائل اپ لوڈ کرو\",\n  },\n};\n\nexport { pa_pk, punjabipk };\n"
  },
  {
    "path": "src/i18n/locales/pa.js",
    "content": "const punjabi = {\r\n  name: \"Punjabi\",\r\n  native_name: \"ਪੰਜਾਬੀ\",\r\n  code: \"pa\",\r\n};\r\n\r\nconst pa = {\r\n  translation: {\r\n    report_bug: \"ਬੱਗ ਦੀ ਰਿਪੋਰਟ ਕਰੋ\",\r\n    import: \"ਇੰਪੋਰਟ ਕਰੋ\",\r\n    import_from: \"ਇੰਪੋਰਟ ਤੋਂ\",\r\n    inherits: \"ਵਿਰਾਸਤ ਵਿੱਚ ਮਿਲਿਆ\",\r\n    merging_column_w_inherited_definition:\r\n      \"ਟੇਬਲ '{{tableName}}' ਵਿੱਚ ਕਾਲਮ '{{fieldName}}' ਵਿਰਾਸਤੀ ਪਰਿਭਾਸ਼ਾ ਨਾਲ ਮਿਲਾਇਆ ਜਾਵੇਗਾ\",\r\n    file: \"ਫਾਈਲ\",\r\n    new: \"ਨਵਾਂ\",\r\n    new_window: \"ਨਵੀਂ ਵਿੰਡੋ\",\r\n    no_saved_diagrams: \"ਤੁਹਾਡੇ ਕੋਲ ਕੋਈ ਸੁਰੱਖਿਅਤ ਡਾਯਾਗ੍ਰਾਮ ਨਹੀਂ ਹਨ\",\r\n    open: \"ਖੋਲ੍ਹੋ\",\r\n    open_recent: \"ਹਾਲੀਆ ਖੋਲ੍ਹੋ\",\r\n    save: \"ਸੁਰੱਖਿਅਤ ਕਰੋ\",\r\n    save_as: \"ਇਸ ਤਰ੍ਹਾਂ ਸੁਰੱਖਿਅਤ ਕਰੋ\",\r\n    save_as_template: \"ਟੈਂਪਲੇਟ ਵਜੋਂ ਸੁਰੱਖਿਅਤ ਕਰੋ\",\r\n    template_saved: \"ਟੈਂਪਲੇਟ ਸੁਰੱਖਿਅਤ ਹੋਇਆ!\",\r\n    rename: \"ਨਾਮ ਬਦਲੋ\",\r\n    delete_diagram: \"ਡਾਯਾਗ੍ਰਾਮ ਮਿਟਾਓ\",\r\n    are_you_sure_delete_diagram:\r\n      \"ਕੀ ਤੁਸੀਂ ਯਕੀਨਨ ਇਸ ਡਾਯਾਗ੍ਰਾਮ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? ਇਹ ਕਾਰਵਾਈ ਪੂਰੀ ਤਰ੍ਹਾਂ ਪਲਟਣਯੋਗ ਨਹੀਂ ਹੈ।\",\r\n    oops_smth_went_wrong: \"ਓਹੋ! ਕੁਝ ਗਲਤ ਹੋ ਗਿਆ।\",\r\n    import_diagram: \"ਡਾਯਾਗ੍ਰਾਮ ਇੰਪੋਰਟ ਕਰੋ\",\r\n    import_from_source: \"SQL ਤੋਂ ਇੰਪੋਰਟ ਕਰੋ\",\r\n    export_as: \"ਇਸ ਤਰ੍ਹਾਂ ਐਕਸਪੋਰਟ ਕਰੋ\",\r\n    export_source: \"SQL ਐਕਸਪੋਰਟ ਕਰੋ\",\r\n    models: \"ਮਾਡਲ\",\r\n    exit: \"ਬਾਹਰ ਜਾਓ\",\r\n    edit: \"ਸੋਧੋ\",\r\n    undo: \"ਅਣਡੂੰਹ ਕਰੋ\",\r\n    redo: \"ਫਿਰ ਕਰੋ\",\r\n    clear: \"ਸਾਫ਼ ਕਰੋ\",\r\n    are_you_sure_clear:\r\n      \"ਕੀ ਤੁਸੀਂ ਯਕੀਨਨ ਇਸ ਡਾਯਾਗ੍ਰਾਮ ਨੂੰ ਸਾਫ਼ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਇਹ ਕਾਰਵਾਈ ਪੂਰੀ ਤਰ੍ਹਾਂ ਪਲਟਣਯੋਗ ਨਹੀਂ ਹੈ।\",\r\n    cut: \"ਕਾਟੋ\",\r\n    copy: \"ਕਾਪੀ ਕਰੋ\",\r\n    paste: \"ਚਿਪਕਾਓ\",\r\n    duplicate: \"ਨਕਲ ਕਰੋ\",\r\n    delete: \"ਮਿਟਾਓ\",\r\n    copy_as_image: \"ਤਸਵੀਰ ਵਜੋਂ ਕਾਪੀ ਕਰੋ\",\r\n    view: \"ਵੇਖੋ\",\r\n    header: \"ਮੇਨੂਬਾਰ\",\r\n    sidebar: \"ਸਾਈਡਬਾਰ\",\r\n    issues: \"ਮੁੱਦੇ\",\r\n    presentation_mode: \"ਪੇਸ਼ਕਾਰੀ ਮੋਡ\",\r\n    strict_mode: \"ਸਖ਼ਤ ਮੋਡ\",\r\n    field_details: \"ਖੇਤਰ ਵੇਰਵਾ\",\r\n    reset_view: \"ਵੇਖਣ ਨੂੰ ਰੀਸੈਟ ਕਰੋ\",\r\n    show_grid: \"ਗਰਿੱਡ ਦਿਖਾਓ\",\r\n    snap_to_grid: \"ਗਰਿੱਡ ਤੇ ਸਨੈਪ ਕਰੋ\",\r\n    show_datatype: \"ਡੇਟਾਟਾਈਪ ਦਿਖਾਓ\",\r\n    show_cardinality: \"ਕਾਰਡਿਨੈਲਿਟੀ ਦਿਖਾਓ\",\r\n    theme: \"ਥੀਮ\",\r\n    light: \"ਹਲਕਾ\",\r\n    dark: \"ਹਨੇਰਾ\",\r\n    zoom_in: \"ਜ਼ੂਮ ਇਨ\",\r\n    zoom_out: \"ਜ਼ੂਮ ਆਊਟ\",\r\n    fullscreen: \"ਪੂਰੀ ਸਕਰੀਨ\",\r\n    settings: \"ਸੈਟਿੰਗ\",\r\n    show_timeline: \"ਟਾਈਮਲਾਈਨ ਦਿਖਾਓ\",\r\n    autosave: \"ਆਟੋ ਸੇਵ\",\r\n    panning: \"ਪੈਨਿੰਗ\",\r\n    show_debug_coordinates: \"ਡੀਬੱਗ ਕੋਆਰਡੀਨੇਟ ਦਿਖਾਓ\",\r\n    transform: \"ਟ੍ਰਾਂਸਫਾਰਮ\",\r\n    viewbox: \"ਵਿਊ ਬਾਕਸ\",\r\n    cursor_coordinates: \"ਕਰਸਰ ਕੋਆਰਡੀਨੇਟ\",\r\n    coordinate_space: \"ਸਪੇਸ\",\r\n    coordinate_space_screen: \"ਸਕ੍ਰੀਨ\",\r\n    coordinate_space_diagram: \"ਡਾਯਾਗ੍ਰਾਮ\",\r\n    table_width: \"ਟੇਬਲ ਦੀ ਚੌੜਾਈ\",\r\n    language: \"ਭਾਸ਼ਾ\",\r\n    flush_storage: \"ਸਟੋਰੇਜ ਸਾਫ਼ ਕਰੋ\",\r\n    are_you_sure_flush_storage:\r\n      \"ਕੀ ਤੁਸੀਂ ਯਕੀਨਨ ਸਟੋਰੇਜ ਨੂੰ ਸਾਫ਼ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਇਹ ਤੁਹਾਡੇ ਸਾਰੇ ਡਾਯਾਗ੍ਰਾਮ ਅਤੇ ਕਸਟਮ ਟੈਂਪਲੇਟਾਂ ਨੂੰ ਪੂਰੀ ਤਰ੍ਹਾਂ ਪੱਕੇ ਤੌਰ 'ਤੇ ਹਟਾ ਦੇਵੇਗਾ।\",\r\n    storage_flushed: \"ਸਟੋਰੇਜ ਸਾਫ਼ ਕੀਤਾ ਗਿਆ\",\r\n    help: \"ਮਦਦ\",\r\n    shortcuts: \"ਸ਼ਾਰਟਕਟ\",\r\n    ask_on_discord: \"ਸਾਡੇ ਤੋਂ Discord 'ਤੇ ਪੁੱਛੋ\",\r\n    feedback: \"ਫੀਡਬੈਕ\",\r\n    no_changes: \"ਕੋਈ ਬਦਲਾਅ ਨਹੀਂ\",\r\n    loading: \"ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ...\",\r\n    last_saved: \"ਆਖਰੀ ਵਾਰ ਸੁਰੱਖਿਅਤ ਕੀਤਾ\",\r\n    saving: \"ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ...\",\r\n    failed_to_save: \"ਸੁਰੱਖਿਅਤ ਕਰਨ ਵਿੱਚ ਅਸਫਲ\",\r\n    fit_window_reset: \"ਵਿੰਡੋ ਫਿਟ / ਰੀਸੈਟ ਕਰੋ\",\r\n    zoom: \"ਜ਼ੂਮ\",\r\n    add_table: \"ਟੇਬਲ ਸ਼ਾਮਲ ਕਰੋ\",\r\n    add_area: \"ਖੇਤਰ ਸ਼ਾਮਲ ਕਰੋ\",\r\n    add_note: \"ਨੋਟ ਸ਼ਾਮਲ ਕਰੋ\",\r\n    add_type: \"ਕਿਸਮ ਸ਼ਾਮਲ ਕਰੋ\",\r\n    to_do: \"ਕਰਨ ਲਈ\",\r\n    tables: \"ਟੇਬਲ\",\r\n    relationships: \"ਸਬੰਧ\",\r\n    subject_areas: \"ਵਿਸ਼ਾ ਖੇਤਰ\",\r\n    notes: \"ਨੋਟ\",\r\n    types: \"ਕਿਸਮਾਂ\",\r\n    search: \"ਖੋਜੋ...\",\r\n    no_tables: \"ਕੋਈ ਟੇਬਲ ਨਹੀਂ\",\r\n    no_tables_text: \"ਆਪਣਾ ਡਾਯਾਗ੍ਰਾਮ ਬਣਾਉਣਾ ਸ਼ੁਰੂ ਕਰੋ!\",\r\n    no_relationships: \"ਕੋਈ ਸਬੰਧ ਨਹੀਂ\",\r\n    no_relationships_text: \"ਖੇਤਰਾਂ ਨੂੰ ਜੋੜਨ ਲਈ ਖਿੱਚੋ ਅਤੇ ਸਬੰਧ ਬਣਾਓ!\",\r\n    no_subject_areas: \"ਕੋਈ ਵਿਸ਼ਾ ਖੇਤਰ ਨਹੀਂ\",\r\n    no_subject_areas_text: \"ਟੇਬਲਾਂ ਨੂੰ ਗਰੁੱਪ ਕਰਨ ਲਈ ਵਿਸ਼ਾ ਖੇਤਰ ਸ਼ਾਮਲ ਕਰੋ!\",\r\n    no_notes: \"ਕੋਈ ਨੋਟ ਨਹੀਂ\",\r\n    no_notes_text: \"ਵਾਧੂ ਜਾਣਕਾਰੀ ਰਿਕਾਰਡ ਕਰਨ ਲਈ ਨੋਟਾਂ ਦੀ ਵਰਤੋਂ ਕਰੋ\",\r\n    no_types: \"ਕੋਈ ਕਿਸਮਾਂ ਨਹੀਂ\",\r\n    no_types_text: \"ਆਪਣੇ ਆਪ ਦੇ ਕਸਟਮ ਡੇਟਾ ਕਿਸਮਾਂ ਬਣਾਓ\",\r\n    no_issues: \"ਕੋਈ ਸਮੱਸਿਆ ਨਹੀਂ ਮਿਲੀ।\",\r\n    strict_mode_is_on_no_issues:\r\n      \"ਸਖ਼ਤ ਮੋਡ ਬੰਦ ਹੈ, ਇਸ ਲਈ ਕੋਈ ਸਮੱਸਿਆ ਦਿਖਾਈ ਨਹੀਂ ਜਾਵੇਗੀ।\",\r\n    name: \"ਨਾਮ\",\r\n    type: \"ਕਿਸਮ\",\r\n    null: \"ਨੱਲ\",\r\n    not_null: \"ਨੱਟ ਨੱਲ\",\r\n    nullable: \"ਨੱਲੇਬਲ\",\r\n    primary: \"ਪ੍ਰਾਈਮਰੀ\",\r\n    unique: \"ਅਨੋਖਾ\",\r\n    autoincrement: \"ਆਟੋ-ਇੰਕਰੀਮੈਂਟ\",\r\n    default_value: \"ਡਿਫਾਲਟ ਮੁੱਲ\",\r\n    check: \"ਚੈੱਕ ਐਕਸਪਰੈਸ਼ਨ\",\r\n    this_will_appear_as_is:\r\n      \"*ਇਹ ਜਨਰੇਟ ਕੀਤੀ ਸਕ੍ਰਿਪਟ ਵਿੱਚ ਇਸ ਤਰ੍ਹਾਂ ਹੀ ਦਿਖਾਈ ਦੇਵੇਗਾ।\",\r\n    comment: \"ਟਿੱਪਣੀ\",\r\n    add_field: \"ਖੇਤਰ ਸ਼ਾਮਲ ਕਰੋ\",\r\n    values: \"ਮੁੱਲ\",\r\n    size: \"ਆਕਾਰ\",\r\n    precision: \"ਸਟੀਕਤਾ\",\r\n    set_precision: \"ਸਟੀਕਤਾ ਸੈਟ ਕਰੋ: 'ਆਕਾਰ, ਅੰਕ'\",\r\n    use_for_batch_input: \"ਬੈਚ ਇਨਪੁੱਟ ਲਈ ਕਾਮੇ (,) ਦੀ ਵਰਤੋਂ ਕਰੋ\",\r\n    indices: \"ਇੰਡਾਈਸ\",\r\n    add_index: \"ਇੰਡੈਕਸ ਸ਼ਾਮਲ ਕਰੋ\",\r\n    select_fields: \"ਖੇਤਰ ਚੁਣੋ\",\r\n    title: \"ਸਿਰਲੇਖ\",\r\n    not_set: \"ਸੈਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ\",\r\n    foreign: \"ਵਿਦੇਸ਼ੀ\",\r\n    cardinality: \"ਕਾਰਡਿਨੈਲਿਟੀ\",\r\n    on_update: \"ਅੱਪਡੇਟ 'ਤੇ\",\r\n    on_delete: \"ਹਟਾਓ 'ਤੇ\",\r\n    swap: \"ਸਵੈਪ ਕਰੋ\",\r\n    one_to_one: \"ਇੱਕ ਤੋਂ ਇੱਕ\",\r\n    one_to_many: \"ਇੱਕ ਤੋਂ ਬਹੁਤ\",\r\n    many_to_one: \"ਬਹੁਤ ਤੋਂ ਇੱਕ\",\r\n    content: \"ਸਮੱਗਰੀ\",\r\n    types_info:\r\n      \"ਇਹ ਫੀਚਰ object-relational DBMS ਜਿਵੇਂ ਕਿ PostgreSQL ਲਈ ਹੈ।\\nਜੇ MySQL ਜਾਂ MariaDB ਲਈ ਵਰਤੀ ਜਾਂਦੀ ਹੈ, ਤਾਂ ਇੱਕ JSON ਕਿਸਮ ਜਨਰੇਟ ਕੀਤੀ ਜਾਵੇਗੀ ਜਿਸ ਵਿੱਚ ਸੰਬੰਧਿਤ json ਵੈਧਤਾ ਚੈੱਕ ਹੋਵੇਗੀ।\\nਜੇ SQLite ਲਈ ਵਰਤੀ ਜਾਵੇ ਤਾਂ ਇਸਨੂੰ BLOB ਵਿੱਚ ਬਦਲਿਆ ਜਾਵੇਗਾ।\\nਜੇ MSSQL ਲਈ ਵਰਤੀ ਜਾਵੇ ਤਾਂ ਪਹਿਲੇ ਖੇਤਰ ਲਈ ਇੱਕ ਕਿਸਮ ਉਪਨਾਮ ਜਨਰੇਟ ਕੀਤਾ ਜਾਵੇਗਾ।\",\r\n    table_deleted: \"ਟੇਬਲ ਮਿਟਾਈ ਗਈ\",\r\n    area_deleted: \"ਖੇਤਰ ਮਿਟਾਇਆ ਗਿਆ\",\r\n    note_deleted: \"ਨੋਟ ਮਿਟਾਇਆ ਗਿਆ\",\r\n    relationship_deleted: \"ਸਬੰਧ ਮਿਟਾਇਆ ਗਿਆ\",\r\n    type_deleted: \"ਕਿਸਮ ਮਿਟਾਈ ਗਈ\",\r\n    cannot_connect: \"ਕਨੈਕਟ ਨਹੀਂ ਕਰ ਸਕਦੇ, ਕਾਲਮ ਦੀਆਂ ਕਿਸਮਾਂ ਵੱਖ-ਵੱਖ ਹਨ\",\r\n    copied_to_clipboard: \"ਕਲਿੱਪਬੋਰਡ 'ਤੇ ਕਾਪੀ ਕੀਤਾ ਗਿਆ\",\r\n    create_new_diagram: \"ਨਵਾਂ ਡਾਯਾਗ੍ਰਾਮ ਬਣਾਓ\",\r\n    cancel: \"ਰੱਦ ਕਰੋ\",\r\n    open_diagram: \"ਡਾਯਾਗ੍ਰਾਮ ਖੋਲ੍ਹੋ\",\r\n    rename_diagram: \"ਡਾਯਾਗ੍ਰਾਮ ਦਾ ਨਾਮ ਬਦਲੋ\",\r\n    export: \"ਐਕਸਪੋਰਟ ਕਰੋ\",\r\n    export_image: \"ਤਸਵੀਰ ਐਕਸਪੋਰਟ ਕਰੋ\",\r\n    create: \"ਬਣਾਓ\",\r\n    confirm: \"ਪੁਸ਼ਟੀ ਕਰੋ\",\r\n    last_modified: \"ਆਖਰੀ ਵਾਰ ਬਦਲਿਆ ਗਿਆ\",\r\n    drag_and_drop_files:\r\n      \"ਫਾਈਲ ਨੂੰ ਇੱਥੇ ਖਿੱਚੋ ਅਤੇ ਛੱਡੋ ਜਾਂ ਅੱਪਲੋਡ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ।\",\r\n    upload_sql_to_generate_diagrams:\r\n      \"ਆਪਣੇ ਟੇਬਲਾਂ ਅਤੇ ਕਾਲਮਾਂ ਨੂੰ ਆਪਣੇ-ਆਪ ਜਨਰੇਟ ਕਰਨ ਲਈ ਇੱਕ SQL ਫਾਈਲ ਅੱਪਲੋਡ ਕਰੋ।\",\r\n    overwrite_existing_diagram: \"ਮੌਜੂਦਾ ਡਾਯਾਗ੍ਰਾਮ ਨੂੰ ਓਵਰਰਾਈਟ ਕਰੋ\",\r\n    only_mysql_supported:\r\n      \"*ਇਸ ਸਮੇਂ ਸਿਰਫ MySQL ਸਕ੍ਰਿਪਟਾਂ ਨੂੰ ਲੋਡ ਕਰਨਾ ਸੰਭਵ ਹੈ।\",\r\n    blank: \"ਖਾਲੀ\",\r\n    filename: \"ਫਾਈਲ ਨਾਮ\",\r\n    table_w_no_name: \"ਬਿਨਾਂ ਨਾਮ ਵਾਲੀ ਟੇਬਲ ਘੋਸ਼ਿਤ ਕੀਤੀ ਗਈ\",\r\n    duplicate_table_by_name: \"ਨਾਮ '{{tableName}}' ਨਾਲ ਨਕਲ ਟੇਬਲ\",\r\n    empty_field_name: \"ਟੇਬਲ '{{tableName}}' ਵਿੱਚ ਖਾਲੀ ਖੇਤਰ `ਨਾਮ`\",\r\n    empty_field_type: \"ਟੇਬਲ '{{tableName}}' ਵਿੱਚ ਖਾਲੀ ਖੇਤਰ `ਕਿਸਮ`\",\r\n    no_values_for_field:\r\n      \"ਟੇਬਲ '{{tableName}}' ਦੇ ਖੇਤਰ '{{fieldName}}' ਦੀ ਕਿਸਮ `{{type}}` ਹੈ ਪਰ ਕੋਈ ਮੁੱਲ ਨਿਰਧਾਰਤ ਨਹੀਂ ਹੈ\",\r\n    default_doesnt_match_type:\r\n      \"ਟੇਬਲ '{{tableName}}' ਦੇ ਖੇਤਰ '{{fieldName}}' ਦਾ ਡਿਫਾਲਟ ਮੁੱਲ ਉਸਦੀ ਕਿਸਮ ਨਾਲ ਮੇਲ ਨਹੀਂ ਖਾਂਦਾ\",\r\n    not_null_is_null:\r\n      \"ਟੇਬਲ '{{tableName}}' ਦਾ ਖੇਤਰ '{{fieldName}}' NOT NULL ਹੈ ਪਰ ਡਿਫਾਲਟ NULL ਹੈ\",\r\n    duplicate_fields:\r\n      \"ਟੇਬਲ '{{tableName}}' ਵਿੱਚ '{{fieldName}}' ਨਾਮ ਵਾਲੇ ਨਕਲ ਖੇਤਰ\",\r\n    duplicate_index:\r\n      \"ਟੇਬਲ '{{tableName}}' ਵਿੱਚ '{{indexName}}' ਨਾਮ ਵਾਲਾ ਨਕਲ ਇੰਡੈਕਸ\",\r\n    empty_index:\r\n      \"ਟੇਬਲ '{{tableName}}' ਵਿੱਚ ਇੰਡੈਕਸ ਕਿਸੇ ਵੀ ਕਾਲਮ ਨੂੰ ਇੰਡੈਕਸ ਨਹੀਂ ਕਰਦਾ\",\r\n    no_primary_key: \"ਟੇਬਲ '{{tableName}}' ਵਿੱਚ ਕੋਈ ਮੁੱਖ ਕੁੰਜੀ ਨਹੀਂ ਹੈ\",\r\n    type_with_no_name: \"ਬਿਨਾਂ ਨਾਮ ਵਾਲੀ ਕਿਸਮ ਘੋਸ਼ਿਤ ਕੀਤੀ ਗਈ\",\r\n    duplicate_types: \"ਨਾਮ '{{typeName}}' ਵਾਲੀਆਂ ਨਕਲ ਕਿਸਮਾਂ\",\r\n    type_w_no_fields:\r\n      \"ਬਿਨਾਂ ਖੇਤਰਾਂ ਵਾਲੀ ਕਿਸਮ '{{typeName}}' ਘੋਸ਼ਿਤ ਕੀਤੀ ਗਈ\",\r\n    empty_type_field_name: \"ਕਿਸਮ '{{typeName}}' ਵਿੱਚ ਖਾਲੀ ਖੇਤਰ `ਨਾਮ`\",\r\n    empty_type_field_type: \"ਕਿਸਮ '{{typeName}}' ਵਿੱਚ ਖਾਲੀ ਖੇਤਰ `ਕਿਸਮ`\",\r\n    no_values_for_type_field:\r\n      \"ਕਿਸਮ '{{typeName}}' ਦੇ ਖੇਤਰ '{{fieldName}}' ਦੀ ਕਿਸਮ `{{type}}` ਹੈ ਪਰ ਕੋਈ ਮੁੱਲ ਨਿਰਧਾਰਤ ਨਹੀਂ ਹੈ\",\r\n    duplicate_type_fields:\r\n      \"ਕਿਸਮ '{{typeName}}' ਵਿੱਚ '{{fieldName}}' ਨਾਮ ਵਾਲੇ ਨਕਲ ਖੇਤਰ\",\r\n    duplicate_reference: \"ਨਾਮ '{{refName}}' ਵਾਲਾ ਨਕਲ ਹਵਾਲਾ\",\r\n    circular_dependency: \"ਟੇਬਲ '{{refName}}' ਵਿੱਚ ਚੱਕਰੀ ਨਿਰਭਰਤਾ\",\r\n    timeline: \"ਟਾਈਮਲਾਈਨ\",\r\n    priority: \"ਤਰਜੀਹ\",\r\n    none: \"ਕੋਈ ਨਹੀਂ\",\r\n    low: \"ਘੱਟ\",\r\n    medium: \"ਦਰਮਿਆਨਾ\",\r\n    high: \"ਵੱਧ\",\r\n    sort_by: \"ਇਸ ਅਨੁਸਾਰ ਕ੍ਰਮਬੱਧ ਕਰੋ\",\r\n    my_order: \"ਮੇਰਾ ਕ੍ਰਮ\",\r\n    completed: \"ਪੂਰਾ ਹੋਇਆ\",\r\n    alphabetically: \"ਵਰਣਮਾਲਾ ਅਨੁਸਾਰ\",\r\n    add_task: \"ਕੰਮ ਸ਼ਾਮਲ ਕਰੋ\",\r\n    details: \"ਵੇਰਵੇ\",\r\n    no_tasks: \"ਤੁਹਾਡੇ ਕੋਲ ਅਜੇ ਤੱਕ ਕੋਈ ਕੰਮ ਨਹੀਂ ਹੈ।\",\r\n    no_activity: \"ਤੁਹਾਡੇ ਕੋਲ ਅਜੇ ਤੱਕ ਕੋਈ ਗਤੀਵਿਧੀ ਨਹੀਂ ਹੈ।\",\r\n    move_element: \"{{name}} ਨੂੰ {{coords}} 'ਤੇ ਲਿਜਾਓ\",\r\n    edit_area: \"{{extra}} ਖੇਤਰ ਸੋਧੋ {{areaName}}\",\r\n    delete_area: \"ਖੇਤਰ ਮਿਟਾਓ {{areaName}}\",\r\n    edit_note: \"{{extra}} ਨੋਟ ਸੋਧੋ {{noteTitle}}\",\r\n    delete_note: \"ਨੋਟ ਮਿਟਾਓ {{noteTitle}}\",\r\n    edit_table: \"{{extra}} ਟੇਬਲ ਸੋਧੋ {{tableName}}\",\r\n    delete_table: \"ਟੇਬਲ ਮਿਟਾਓ {{tableName}}\",\r\n    edit_type: \"{{extra}} ਕਿਸਮ ਸੋਧੋ {{typeName}}\",\r\n    delete_type: \"ਕਿਸਮ ਮਿਟਾਓ {{typeName}}\",\r\n    add_relationship: \"ਸਬੰਧ ਸ਼ਾਮਲ ਕਰੋ\",\r\n    edit_relationship: \"{{extra}} ਸਬੰਧ ਸੋਧੋ {{refName}}\",\r\n    delete_relationship: \"ਸਬੰਧ ਮਿਟਾਓ {{refName}}\",\r\n    not_found: \"ਨਹੀਂ ਮਿਲਿਆ\",\r\n    pick_db: \"ਇੱਕ ਡਾਟਾਬੇਸ ਚੁਣੋ\",\r\n    generic: \"ਜੈਨਰਿਕ\",\r\n    generic_description:\r\n      \"ਜੈਨਰਿਕ ਡਾਯਾਗ੍ਰਾਮਾਂ ਨੂੰ ਕਿਸੇ ਵੀ SQL ਫਲੇਵਰ ਵਿੱਚ ਐਕਸਪੋਰਟ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ ਪਰ ਘੱਟ ਡੇਟਾ ਕਿਸਮਾਂ ਦਾ ਸਮਰਥਨ ਕਰਦੇ ਹਨ।\",\r\n    enums: \"ਇਨੱਮ\",\r\n    add_enum: \"ਇਨੱਮ ਸ਼ਾਮਲ ਕਰੋ\",\r\n    edit_enum: \"{{extra}} ਇਨੱਮ ਸੋਧੋ {{enumName}}\",\r\n    delete_enum: \"ਇਨੱਮ ਮਿਟਾਓ\",\r\n    enum_w_no_name: \"ਬਿਨਾਂ ਨਾਮ ਵਾਲਾ ਇਨੱਮ ਮਿਲਿਆ\",\r\n    enum_w_no_values: \"ਬਿਨਾਂ ਮੁੱਲਾਂ ਵਾਲਾ ਇਨੱਮ '{{enumName}}' ਮਿਲਿਆ\",\r\n    duplicate_enums: \"ਨਾਮ '{{enumName}}' ਵਾਲੇ ਡੁਪਲੀਕੇਟ ਇਨੱਮ\",\r\n    enum_deleted: \"ਇਨੱਮ ਮਿਟਾਇਆ ਗਿਆ\",\r\n    no_enums: \"ਕੋਈ ਇਨੱਮ ਨਹੀਂ\",\r\n    no_enums_text: \"ਇੱਥੇ ਇਨੱਮ ਪਰਿਭਾਸ਼ਿਤ ਕਰੋ\",\r\n    declare_array: \"ਐਰੇ ਘੋਸ਼ਿਤ ਕਰੋ\",\r\n    empty_index_name: \"ਟੇਬਲ '{{tableName}}' ਵਿੱਚ ਬਿਨਾਂ ਨਾਮ ਵਾਲਾ ਇੰਡੈਕਸ ਘੋਸ਼ਿਤ ਕੀਤਾ\",\r\n    didnt_find_diagram: \"ਓਹੋ! ਡਾਯਾਗ੍ਰਾਮ ਨਹੀਂ ਮਿਲਿਆ।\",\r\n    unsigned: \"ਅਨਸਾਈਨਡ\",\r\n    share: \"ਸਾਂਝਾ ਕਰੋ\",\r\n    unshare: \"ਸਾਂਝਾ ਕਰਨਾ ਬੰਦ ਕਰੋ\",\r\n    copy_link: \"ਲਿੰਕ ਕਾਪੀ ਕਰੋ\",\r\n    readme: \"README\",\r\n    failed_to_load: \"ਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਲਿੰਕ ਸਹੀ ਹੈ।\",\r\n    share_info:\r\n      \"* ਇਸ ਲਿੰਕ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਨਾਲ ਲਾਈਵ ਰੀਅਲ-ਟਾਈਮ ਸਹਿਯੋਗ ਸੈਸ਼ਨ ਨਹੀਂ ਬਣਾਇਆ ਜਾਵੇਗਾ।\",\r\n    show_relationship_labels: \"ਰਿਸ਼ਤਿਆਂ ਦੇ ਲੇਬਲ ਦਿਖਾਓ\",\r\n    docs: \"ਡੌਕਸ\",\r\n    supported_types: \"ਸਮਰਥਿਤ ਫਾਈਲ ਕਿਸਮਾਂ:\",\r\n    bulk_update: \"ਬਲਕ ਅਪਡੇਟ\",\r\n    multiselect: \"ਮਲਟੀਸਲੈਕਟ\",\r\n    export_saved_data: \"ਸੇਵ ਕੀਤਾ ਡੇਟਾ ਐਕਸਪੋਰਟ ਕਰੋ\",\r\n    dbml_view: \"DBML ਵਿਊ\",\r\n    tab_view: \"ਟੈਬ ਵਿਊ\",\r\n    label: \"ਲੇਬਲ\",\r\n    many_side_label: \"ਕਈ(ਨ) ਪਾਸੇ ਲੇਬਲ\",\r\n    version: \"ਵਰਜਨ\",\r\n    versions: \"ਵਰਜਨ\",\r\n    no_saved_versions: \"ਕੋਈ ਸੇਵ ਕੀਤੇ ਵਰਜਨ ਨਹੀਂ\",\r\n    record_version: \"ਵਰਜਨ ਰਿਕਾਰਡ ਕਰੋ\",\r\n    commited_at: \"ਕਮਿਟ ਕੀਤਾ\",\r\n    read_only: \"ਸਿਰਫ ਪੜ੍ਹਨ ਲਈ\",\r\n    continue: \"ਜਾਰੀ ਰੱਖੋ\",\r\n    restore_version: \"ਵਰਜਨ ਰੀਸਟੋਰ ਕਰੋ\",\r\n    restore_warning: \"ਦੂਜਾ ਵਰਜਨ ਲੋਡ ਕਰਨਾ ਕੋਈ ਵੀ ਬਦਲਾਅ ਓਵਰਰਾਈਟ ਕਰ ਦੇਵੇਗਾ।\",\r\n    return_to_current: \"ਡਾਯਾਗ੍ਰਾਮ 'ਤੇ ਵਾਪਸ ਜਾਓ\",\r\n    no_changes_to_record: \"ਰਿਕਾਰਡ ਕਰਨ ਲਈ ਕੋਈ ਬਦਲਾਅ ਨਹੀਂ\",\r\n    click_to_view: \"ਵੇਖਣ ਲਈ ਕਲਿੱਕ ਕਰੋ\",\r\n    load_more: \"ਹੋਰ ਲੋਡ ਕਰੋ\",\r\n    clear_cache: \"ਕੈਸ਼ ਸਾਫ਼ ਕਰੋ\",\r\n    cache_cleared: \"ਕੈਸ਼ ਸਾਫ਼ ਕੀਤਾ ਗਿਆ\",\r\n    failed_to_record_version: \"ਵਰਜਨ ਰਿਕਾਰਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ\",\r\n    failed_to_load_diagram: \"ਡਾਯਾਗ੍ਰਾਮ ਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ\",\r\n    see_all: \"ਸਭ ਵੇਖੋ\",\r\n    insert_sql: \"SQL ਇੰਸਰਟ ਕਰੋ\",\r\n    upload_file: \"ਫਾਈਲ ਅੱਪਲੋਡ ਕਰੋ\",\r\n  },\r\n};\r\n\r\nexport { pa, punjabi };\r\n"
  },
  {
    "path": "src/i18n/locales/pl.js",
    "content": "const polish = {\n  name: \"Polish\",\n  native_name: \"Polski\",\n  code: \"pl\",\n};\n\nconst pl = {\n  translation: {\n    report_bug: \"Zgłoś błąd\",\n    import_from: \"Importuj\",\n    import: \"Importuj\",\n    file: \"Plik\",\n    new: \"Nowy\",\n    new_window: \"Nowe okno\",\n    open: \"Otwórz\",\n    save: \"Zapisz\",\n    save_as: \"Zapisz jako\",\n    save_as_template: \"Zapisz jako szablon\",\n    template_saved: \"Szablon zapisany!\",\n    rename: \"Zmień nazwę\",\n    delete_diagram: \"Usuń diagram\",\n    are_you_sure_delete_diagram:\n      \"Czy na pewno chcesz usunąć ten diagram? Ta operacja jest nieodwracalna.\",\n    oops_smth_went_wrong: \"Ups! Coś poszło nie tak.\",\n    import_diagram: \"Importuj diagram\",\n    import_from_source: \"Importuj z SQL\",\n    export_as: \"Eksportuj jako\",\n    export_source: \"Eksportuj SQL\",\n    models: \"Modele\",\n    exit: \"Wyjdź\",\n    edit: \"Edytuj\",\n    undo: \"Cofnij\",\n    redo: \"Ponów\",\n    clear: \"Wyczyść\",\n    are_you_sure_clear:\n      \"Czy na pewno chcesz wyczyścić diagram? To jest nieodwracalne.\",\n    cut: \"Wytnij\",\n    copy: \"Kopiuj\",\n    paste: \"Wklej\",\n    duplicate: \"Duplikuj\",\n    delete: \"Usuń\",\n    copy_as_image: \"Kopiuj jako obraz\",\n    view: \"Widok\",\n    header: \"Pasek menu\",\n    sidebar: \"Pasek boczny\",\n    issues: \"Problemy\",\n    presentation_mode: \"Tryb prezentacji\",\n    strict_mode: \"Tryb ścisły\",\n    field_details: \"Szczegóły pola\",\n    reset_view: \"Resetuj widok\",\n    show_grid: \"Pokaż siatkę\",\n    show_cardinality: \"Pokaż krotność\",\n    theme: \"Motyw\",\n    light: \"Jasny\",\n    dark: \"Ciemny\",\n    zoom_in: \"Powiększ\",\n    zoom_out: \"Pomniejsz\",\n    fullscreen: \"Pełny ekran\",\n    settings: \"Ustawienia\",\n    show_timeline: \"Pokaż oś czasu\",\n    autosave: \"Automatyczne zapisywanie\",\n    panning: \"Przesuwanie\",\n    show_debug_coordinates: \"Pokaż współrzędne debugowania\",\n    transform: \"Przekształć\",\n    viewbox: \"Obszar widoku\",\n    cursor_coordinates: \"Współrzędne kursora\",\n    coordinate_space: \"Przestrzeń\",\n    coordinate_space_screen: \"Ekran\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Szerokość tabeli\",\n    language: \"Język\",\n    flush_storage: \"Wyczyść pamięć\",\n    are_you_sure_flush_storage:\n      \"Czy na pewno chcesz wyczyścić pamięć? To nieodwracalnie usunie wszystkie twoje diagramy i własne szablony.\",\n    storage_flushed: \"Pamięć wyczyszczona\",\n    help: \"Pomoc\",\n    shortcuts: \"Skróty\",\n    ask_on_discord: \"Zapytaj nas na Discordzie\",\n    feedback: \"Opinie\",\n    no_changes: \"Brak zmian\",\n    loading: \"Ładowanie...\",\n    last_saved: \"Ostatnio zapisane\",\n    saving: \"Zapisywanie...\",\n    failed_to_save: \"Nie udało się zapisać\",\n    fit_window_reset: \"Dopasuj okno / Resetuj\",\n    zoom: \"Powiększenie\",\n    add_table: \"Dodaj tabelę\",\n    add_area: \"Dodaj obszar\",\n    add_note: \"Dodaj notatkę\",\n    add_type: \"Dodaj typ\",\n    to_do: \"Do zrobienia\",\n    tables: \"Tabele\",\n    relationships: \"Relacje\",\n    subject_areas: \"Obszary tematyczne\",\n    notes: \"Notatki\",\n    types: \"Typy\",\n    search: \"Szukaj...\",\n    no_tables: \"Brak tabel\",\n    no_tables_text: \"Zacznij budować swój diagram!\",\n    no_relationships: \"Brak relacji\",\n    no_relationships_text: \"Przeciągnij, aby połączyć pola i tworzyć relacje!\",\n    no_subject_areas: \"Brak obszarów tematycznych\",\n    no_subject_areas_text: \"Dodaj obszary tematyczne, aby grupować tabele!\",\n    no_notes: \"Brak notatek\",\n    no_notes_text: \"Używaj notatek do zapisywania dodatkowych informacji\",\n    no_types: \"Brak typów\",\n    no_types_text: \"Twórz własne typy danych\",\n    no_issues: \"Nie wykryto żadnych problemów.\",\n    strict_mode_is_on_no_issues:\n      \"Tryb ścisły jest wyłączony, więc żadne problemy nie zostaną wyświetlone.\",\n    name: \"Nazwa\",\n    type: \"Typ\",\n    null: \"Null\",\n    not_null: \"Nie null\",\n    primary: \"Klucz główny\",\n    unique: \"Unikalny\",\n    autoincrement: \"Autonumerowanie\",\n    default_value: \"Wartość domyślna\",\n    check: \"Wyrażenie sprawdzające\",\n    this_will_appear_as_is:\n      \"*To pojawi się w wygenerowanym skrypcie tak, jak jest.\",\n    comment: \"Komentarz\",\n    add_field: \"Dodaj pole\",\n    values: \"Wartości\",\n    size: \"Rozmiar\",\n    precision: \"Precyzja\",\n    set_precision: \"Ustaw precyzję: 'rozmiar, cyfry'\",\n    use_for_batch_input: \"Użyj , do wsadowego wprowadzania\",\n    indices: \"Indeksy\",\n    add_index: \"Dodaj indeks\",\n    select_fields: \"Wybierz pola\",\n    title: \"Tytuł\",\n    not_set: \"Nie ustawiono\",\n    foreign: \"Obcy\",\n    cardinality: \"Krotność\",\n    on_update: \"Przy aktualizacji\",\n    on_delete: \"Przy usunięciu\",\n    swap: \"Zamień\",\n    one_to_one: \"Jeden do jednego\",\n    one_to_many: \"Jeden do wielu\",\n    many_to_one: \"Wiele do jednego\",\n    content: \"Zawartość\",\n    types_info:\n      \"Ta funkcja jest przeznaczona dla obiektowo-relacyjnych systemów baz danych, takich jak PostgreSQL.\\nJeśli używana dla MySQL lub MariaDB, zostanie wygenerowany typ JSON z odpowiadającym mu sprawdzeniem walidacji JSON.\\nJeśli używana dla SQLite, zostanie przetłumaczona na BLOB.\\nJeśli używana dla MSSQL, zostanie wygenerowany alias typu do pierwszego pola.\",\n    table_deleted: \"Tabela usunięta\",\n    area_deleted: \"Obszar usunięty\",\n    note_deleted: \"Notatka usunięta\",\n    relationship_deleted: \"Relacja usunięta\",\n    type_deleted: \"Typ usunięty\",\n    cannot_connect: \"Nie można połączyć, kolumny mają różne typy\",\n    copied_to_clipboard: \"Skopiowano do schowka\",\n    create_new_diagram: \"Utwórz nowy diagram\",\n    cancel: \"Anuluj\",\n    open_diagram: \"Otwórz diagram\",\n    rename_diagram: \"Zmień nazwę diagramu\",\n    export: \"Eksportuj\",\n    export_image: \"Eksportuj obraz\",\n    create: \"Utwórz\",\n    confirm: \"Potwierdź\",\n    last_modified: \"Ostatnio zmodyfikowano\",\n    drag_and_drop_files:\n      \"Przeciągnij i upuść plik tutaj lub kliknij, aby przesłać.\",\n    upload_sql_to_generate_diagrams:\n      \"Prześlij plik SQL, aby automatycznie wygenerować tabele i kolumny.\",\n    overwrite_existing_diagram: \"Nadpisz istniejący diagram\",\n    only_mysql_supported:\n      \"*Obecnie obsługiwane jest tylko ładowanie skryptów MySQL.\",\n    blank: \"Pusty\",\n    filename: \"Nazwa pliku\",\n    table_w_no_name: \"Zadeklarowano tabelę bez nazwy\",\n    duplicate_table_by_name: \"Duplikat tabeli o nazwie '{{tableName}}'\",\n    empty_field_name: \"Puste pole `name` w tabeli '{{tableName}}'\",\n    empty_field_type: \"Puste pole `type` w tabeli '{{tableName}}'\",\n    no_values_for_field:\n      \"Pole '{{fieldName}}' w tabeli '{{tableName}}' jest typu `{{type}}`, ale nie określono wartości\",\n    default_doesnt_match_type:\n      \"Wartość domyślna dla pola '{{fieldName}}' w tabeli '{{tableName}}' nie pasuje do jego typu\",\n    not_null_is_null:\n      \"Pole '{{fieldName}}' w tabeli '{{tableName}}' jest NOT NULL, ale ma wartość domyślną NULL\",\n    duplicate_fields:\n      \"Duplikat pól tabeli o nazwie '{{fieldName}}' w tabeli '{{tableName}}'\",\n    duplicate_index:\n      \"Duplikat indeksu o nazwie '{{indexName}}' w tabeli '{{tableName}}'\",\n    empty_index: \"Indeks w tabeli '{{tableName}}' nie indeksuje żadnych kolumn\",\n    no_primary_key: \"Tabela '{{tableName}}' nie ma klucza głównego\",\n    type_with_no_name: \"Zadeklarowano typ bez nazwy\",\n    duplicate_types: \"Duplikat typów o nazwie '{{typeName}}'\",\n    type_w_no_fields: \"Zadeklarowano pusty typ '{{typeName}}' bez pól\",\n    empty_type_field_name: \"Puste pole `name` w typie '{{typeName}}'\",\n    empty_type_field_type: \"Puste pole `type` w typie '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Pole '{{fieldName}}' w typie '{{typeName}}' jest typu `{{type}}`, ale nie określono wartości\",\n    duplicate_type_fields:\n      \"Duplikat pól typu o nazwie '{{fieldName}}' w typie '{{typeName}}'\",\n    duplicate_reference: \"Duplikat referencji o nazwie '{{refName}}'\",\n    circular_dependency: \"Cykliczna zależność obejmująca tabelę '{{refName}}'\",\n    timeline: \"Oś czasu\",\n    priority: \"Priorytet\",\n    none: \"Brak\",\n    low: \"Niski\",\n    medium: \"Średni\",\n    high: \"Wysoki\",\n    sort_by: \"Sortuj według\",\n    my_order: \"Moja kolejność\",\n    completed: \"Ukończone\",\n    alphabetically: \"Alfabetycznie\",\n    add_task: \"Dodaj zadanie\",\n    details: \"Szczegóły\",\n    no_tasks: \"Nie masz jeszcze żadnych zadań.\",\n    no_activity: \"Nie masz jeszcze żadnej aktywności.\",\n    move_element: \"Przenieś {{name}} do {{coords}}\",\n    edit_area: \"{{extra}} Edytuj obszar {{areaName}}\",\n    delete_area: \"Usuń obszar {{areaName}}\",\n    edit_note: \"{{extra}} Edytuj notatkę {{noteTitle}}\",\n    delete_note: \"Usuń notatkę {{noteTitle}}\",\n    edit_table: \"{{extra}} Edytuj tabelę {{tableName}}\",\n    delete_table: \"Usuń tabelę {{tableName}}\",\n    edit_type: \"{{extra}} Edytuj typ {{typeName}}\",\n    delete_type: \"Usuń typ {{typeName}}\",\n    add_relationship: \"Dodaj relację\",\n    edit_relationship: \"{{extra}} Edytuj relację {{refName}}\",\n    delete_relationship: \"Usuń relację {{refName}}\",\n    not_found: \"Nie znaleziono\",\n    pick_db: \"Wybierz bazę danych\",\n    generic: \"Ogólny\",\n    generic_description:\n      \"Ogólne diagramy mogą być eksportowane do dowolnego dialektu SQL, ale obsługują niewiele typów danych.\",\n    enums: \"Wyliczenia\",\n    add_enum: \"Dodaj wyliczenie\",\n    edit_enum: \"{{extra}} Edytuj wyliczenie {{enumName}}\",\n    delete_enum: \"Usuń wyliczenie\",\n    enum_w_no_name: \"Znaleziono wyliczenie bez nazwy\",\n    enum_w_no_values: \"Znaleziono wyliczenie '{{enumName}}' bez wartości\",\n    duplicate_enums: \"Duplikat wyliczeń o nazwie '{{enumName}}'\",\n    no_enums: \"Brak wyliczeń\",\n    no_enums_text: \"Zdefiniuj wyliczenia tutaj\",\n    declare_array: \"Zadeklaruj tablicę\",\n    empty_index_name: \"Zadeklarowano indeks bez nazwy w tabeli '{{tableName}}'\",\n    didnt_find_diagram: \"Ups! Nie znaleziono diagramu.\",\n    unsigned: \"Bez znaku\",\n    share: \"Udostępnij\",\n    copy_link: \"Kopiuj link\",\n    readme: \"README\",\n    failed_to_load:\n      \"Nie udało się załadować. Upewnij się, że link jest poprawny.\",\n    share_info:\n      \"* Udostępnienie tego linku nie utworzy sesji współpracy w czasie rzeczywistym.\",\n  },\n};\n\nexport { pl, polish };\n"
  },
  {
    "path": "src/i18n/locales/pt-br.js",
    "content": "const portuguese = {\n  name: \"Portuguese\",\n  native_name: \"Português\",\n  code: \"pt-BR\",\n};\n\nconst pt = {\n  translation: {\n    report_bug: \"Reportar um erro\",\n    import_from: \"Importar\",\n    import: \"Importar\",\n    file: \"Arquivo\",\n    new: \"Novo\",\n    new_window: \"Nova janela\",\n    open: \"Abrir\",\n    save: \"Salvar\",\n    save_as: \"Salvar como\",\n    save_as_template: \"Salvar como template\",\n    template_saved: \"Template salvo!\",\n    rename: \"Renomear\",\n    delete_diagram: \"Excluir diagrama\",\n    are_you_sure_delete_diagram:\n      \"Tem certeza de que deseja excluir este diagrama? Esta ação é irreversível.\",\n    oops_smth_went_wrong: \"Ops! Algo deu errado.\",\n    import_diagram: \"Importar diagrama\",\n    import_from_source: \"Importar de SQL\",\n    export_as: \"Exportar como\",\n    export_source: \"Exportar SQL\",\n    models: \"Modelos\",\n    exit: \"Sair\",\n    edit: \"Editar\",\n    undo: \"Desfazer\",\n    redo: \"Refazer\",\n    clear: \"Limpar\",\n    are_you_sure_clear:\n      \"Tem certeza de que deseja limpar o diagrama? Isso é irreversível.\",\n    cut: \"Recortar\",\n    copy: \"Copiar\",\n    paste: \"Colar\",\n    duplicate: \"Duplicar\",\n    delete: \"Excluir\",\n    copy_as_image: \"Copiar como imagem\",\n    view: \"Ver\",\n    header: \"Barra de menu\",\n    sidebar: \"Barra lateral\",\n    issues: \"Problemas\",\n    presentation_mode: \"Modo de apresentação\",\n    strict_mode: \"Modo estrito\",\n    field_details: \"Detalhes do campo\",\n    reset_view: \"Redefinir visualização\",\n    show_grid: \"Mostrar grade\",\n    show_datatype: \"Mostrar tipo de dado\",\n    show_cardinality: \"Mostrar cardinalidade\",\n    theme: \"Tema\",\n    light: \"Claro\",\n    dark: \"Escuro\",\n    zoom_in: \"Aumentar zoom\",\n    zoom_out: \"Diminuir zoom\",\n    fullscreen: \"Tela cheia\",\n    settings: \"Configurações\",\n    show_timeline: \"Mostrar linha do tempo\",\n    autosave: \"Salvar automaticamente\",\n    panning: \"Deslocar\",\n    show_debug_coordinates: \"Mostrar coordenadas de depuração\",\n    transform: \"Transformar\",\n    viewbox: \"Área de visualização\",\n    cursor_coordinates: \"Coordenadas do cursor\",\n    coordinate_space: \"Espaço de coordenadas\",\n    coordinate_space_screen: \"Tela\",\n    coordinate_space_diagram: \"Diagrama\",\n    table_width: \"Largura da tabela\",\n    language: \"Idioma\",\n    flush_storage: \"Limpar armazenamento\",\n    are_you_sure_flush_storage:\n      \"Tem certeza de que deseja limpar o armazenamento? Isso irá excluir permanentemente todos os seus diagramas e modelos personalizados.\",\n    storage_flushed: \"Armazenamento limpo\",\n    help: \"Ajuda\",\n    shortcuts: \"Atalhos\",\n    ask_on_discord: \"Pergunte no Discord\",\n    feedback: \"Feedback\",\n    no_changes: \"Sem alterações\",\n    loading: \"Carregando...\",\n    last_saved: \"Última vez salvo às\",\n    saving: \"Salvando...\",\n    failed_to_save: \"Falha ao salvar\",\n    fit_window_reset: \"Ajustar janela / Redefinir\",\n    zoom: \"Zoom\",\n    add_table: \"Adicionar tabela\",\n    add_area: \"Adicionar área\",\n    add_note: \"Adicionar nota\",\n    add_type: \"Adicionar tipo\",\n    to_do: \"Para fazer\",\n    tables: \"Tabelas\",\n    relationships: \"Relacionamentos\",\n    subject_areas: \"Áreas de assunto\",\n    notes: \"Notas\",\n    types: \"Tipos\",\n    search: \"Buscar...\",\n    no_tables: \"Sem tabelas\",\n    no_tables_text: \"Comece a construir seu diagrama!\",\n    no_relationships: \"Sem relacionamentos\",\n    no_relationships_text:\n      \"Arraste para conectar campos e formar relacionamentos!\",\n    no_subject_areas: \"Sem áreas de assunto\",\n    no_subject_areas_text: \"Adicione áreas de assunto para agrupar tabelas!\",\n    no_notes: \"Sem notas\",\n    no_notes_text: \"Use notas para registrar informações extras\",\n    no_types: \"Sem tipos\",\n    no_types_text: \"Crie seus próprios tipos de dados personalizados\",\n    no_issues: \"Nenhum problema foi detectado.\",\n    strict_mode_is_on_no_issues:\n      \"O modo estrito está desativado, portanto, nenhum problema será exibido.\",\n    name: \"Nome\",\n    type: \"Tipo\",\n    null: \"Nulo\",\n    not_null: \"Não nulo\",\n    nullable: \"Nulo\",\n    primary: \"Primário\",\n    unique: \"Único\",\n    autoincrement: \"Auto incremento\",\n    default_value: \"Padrão\",\n    check: \"Verificar expressão\",\n    this_will_appear_as_is: \"*Isso aparecerá no script gerado como está.\",\n    comment: \"Comentário\",\n    add_field: \"Adicionar campo\",\n    values: \"valores\",\n    size: \"Tamanho\",\n    precision: \"Precisão\",\n    set_precision: \"Definir precisão: (tamanho, dígitos)\",\n    use_for_batch_input: \"Usar , para entrada em massa\",\n    indices: \"Índices\",\n    add_index: \"Adicionar índice\",\n    select_fields: \"Selecionar campos\",\n    title: \"Título\",\n    not_set: \"Não definido\",\n    foreign: \"Estrangeiro\",\n    cardinality: \"Cardinalidade\",\n    on_update: \"Na atualização\",\n    on_delete: \"Na exclusão\",\n    swap: \"Trocar\",\n    one_to_one: \"Um para um\",\n    one_to_many: \"Um para muitos\",\n    many_to_one: \"Muitos para um\",\n    content: \"Conteúdo\",\n    types_info:\n      \"Este recurso destina-se a SGBDs objeto-relacionais como PostgreSQL.\\nSe usado para MySQL ou MariaDB, será gerado um tipo JSON com a validação json correspondente.\\nSe usado para SQLite, será traduzido para um BLOB.\\nSe usado para MSSQL, será gerado um alias de tipo para o primeiro campo.\",\n    table_deleted: \"Tabela excluída\",\n    area_deleted: \"Área excluída\",\n    note_deleted: \"Nota excluída\",\n    relationship_deleted: \"Relacionamento excluído\",\n    type_deleted: \"Tipo excluído\",\n    cannot_connect: \"Não é possível conectar, as colunas têm tipos diferentes\",\n    copied_to_clipboard: \"Copiado para a área de transferência\",\n    create_new_diagram: \"Criar novo diagrama\",\n    cancel: \"Cancelar\",\n    open_diagram: \"Abrir diagrama\",\n    rename_diagram: \"Renomear diagrama\",\n    export: \"Exportar\",\n    export_image: \"Exportar imagem\",\n    create: \"Criar\",\n    confirm: \"Confirmar\",\n    last_modified: \"Última modificação\",\n    drag_and_drop_files:\n      \"Arraste e solte o arquivo aqui ou clique para fazer upload.\",\n    upload_sql_to_generate_diagrams:\n      \"Faça o upload de um arquivo SQL para gerar automaticamente suas tabelas e colunas.\",\n    overwrite_existing_diagram: \"Substituir diagrama existente\",\n    only_mysql_supported:\n      \"*Por enquanto, apenas o carregamento de scripts MySQL é suportado.\",\n    blank: \"Em branco\",\n    filename: \"Nome do arquivo\",\n    table_w_no_name: \"Declarada uma tabela sem nome\",\n    duplicate_table_by_name: \"Tabela duplicada com o nome '{{tableName}}'\",\n    empty_field_name: \"Campo `name` vazio na tabela '{{tableName}}'\",\n    empty_field_type: \"Campo `type` vazio na tabela '{{tableName}}'\",\n    no_values_for_field:\n      \"O campo '{{fieldName}}' da tabela '{{tableName}}' é do tipo `{{type}}`, mas nenhum valor foi especificado\",\n    default_doesnt_match_type:\n      \"O valor padrão para o campo '{{fieldName}}' na tabela '{{tableName}}' não corresponde ao seu tipo\",\n    not_null_is_null:\n      \"O campo '{{fieldName}}' da tabela '{{tableName}}' é NOT NULL mas tem o valor padrão NULL\",\n    duplicate_fields:\n      \"Campos de tabela duplicados pelo nome '{{fieldName}}' na tabela '{{tableName}}'\",\n    duplicate_index:\n      \"Índice duplicado pelo nome '{{indexName}}' na tabela '{{tableName}}'\",\n    empty_index: \"O índice na tabela '{{tableName}}' não indexa colunas\",\n    no_primary_key: \"A tabela '{{tableName}}' não tem chave primária\",\n    type_with_no_name: \"Declarado um tipo sem nome\",\n    duplicate_types: \"Tipos duplicados pelo nome '{{typeName}}'\",\n    type_w_no_fields: \"Declarado um tipo vazio '{{typeName}}' sem campos\",\n    empty_type_field_name: \"Campo `name` vazio no tipo '{{typeName}}'\",\n    empty_type_field_type: \"Campo `type` vazio no tipo '{{typeName}}'\",\n    no_values_for_type_field:\n      \"O campo '{{fieldName}}' do tipo '{{typeName}}' é do tipo `{{type}}` mas nenhum valor foi especificado\",\n    duplicate_type_fields:\n      \"Campos de tipo duplicados pelo nome '{{fieldName}}' no tipo '{{typeName}}'\",\n    duplicate_reference: \"Referência duplicada pelo nome '{{refName}}'\",\n    circular_dependency: \"Dependência circular envolvendo tabela '{{refName}}'\",\n    timeline: \"Linha do tempo\",\n    priority: \"Prioridade\",\n    none: \"Nenhuma\",\n    low: \"Baixa\",\n    medium: \"Média\",\n    high: \"Alta\",\n    sort_by: \"Ordenar por\",\n    my_order: \"Minha ordem\",\n    completed: \"Concluído\",\n    alphabetically: \"Alfabeticamente\",\n    add_task: \"Adicionar tarefa\",\n    details: \"Detalhes\",\n    no_tasks: \"Você ainda não possui tarefas.\",\n    no_activity: \"Você ainda não possui atividades.\",\n    move_element: \"Mover {{name}} para {{coords}}\",\n    edit_area: \"{{extra}} Editar área {{areaName}}\",\n    delete_area: \"Excluir área {{areaName}}\",\n    edit_note: \"{{extra}} Editar nota {{noteTitle}}\",\n    delete_note: \"Excluir nota {{noteTitle}}\",\n    edit_table: \"{{extra}} Editar tabela {{tableName}}\",\n    delete_table: \"Excluir tabela {{tableName}}\",\n    edit_type: \"{{extra}} Editar tipo {{typeName}}\",\n    delete_type: \"Excluir tipo {{typeName}}\",\n    add_relationship: \"Adicionar relacionamento\",\n    edit_relationship: \"{{extra}} Editar relacionamento {{refName}}\",\n    delete_relationship: \"Excluir relacionamento {{refName}}\",\n    not_found: \"Não encontrado\",\n    pick_db: \"Escolha um banco de dados\",\n    generic: \"Genérico\",\n    generic_description:\n      \"Diagramas genéricos podem ser exportados para qualquer tipo de SQL, mas suportam poucos tipos de dados.\",\n    enums: \"Enums\",\n    add_enum: \"Adicionar enum\",\n    edit_enum: \"{{extra}} Editar enum {{enumName}}\",\n    delete_enum: \"Excluir enum\",\n    enum_w_no_name: \"Enum encontrado sem nome\",\n    enum_w_no_values: \"Enum '{{enumName}}' encontrado sem valores\",\n    duplicate_enums: \"Enums duplicados com o nome '{{enumName}}'\",\n    no_enums: \"Nenhum enum\",\n    no_enums_text: \"Defina enums aqui\",\n    declare_array: \"Declarar array\",\n    empty_index_name: \"Índice sem nome declarado na tabela '{{tableName}}'\",\n    didnt_find_diagram: \"Ops! Diagrama não encontrado.\",\n    unsigned: \"Sem sinal (unsigned)\",\n    share: \"Compartilhar\",\n    unshare: \"Deixar de compartilhar\",\n    copy_link: \"Copiar link\",\n    readme: \"LEIAME\",\n    failed_to_load: \"Falha ao carregar. Verifique se o link está correto.\",\n    share_info:\n      \"* Compartilhar este link não criará uma sessão de colaboração em tempo real.\",\n    show_relationship_labels: \"Mostrar rótulos de relacionamento\",\n    docs: \"Documentação\",\n    supported_types: \"Tipos de arquivo suportados:\",\n    bulk_update: \"Atualização em massa\",\n    multiselect: \"Seleção múltipla\",\n    export_saved_data: \"Exportar dados salvos\",\n  },\n};\n\nexport { pt, portuguese };"
  },
  {
    "path": "src/i18n/locales/ro.js",
    "content": "const romanian = {\n  name: \"Romanian\",\n  native_name: \"Română\",\n  code: \"ro\",\n};\n\nconst ro = {\n  translation: {\n    report_bug: \"Raportează o eroare\",\n    import_from: \"Import\",\n    import: \"Import\",\n    file: \"Fișier\",\n    new: \"Nou\",\n    new_window: \"Fereastră nouă\",\n    open: \"Deschide\",\n    save: \"Salvează\",\n    save_as: \"Salvează ca\",\n    save_as_template: \"Salvează ca șablon\",\n    template_saved: \"Șablon salvat!!\",\n    rename: \"Redenumi\",\n    delete_diagram: \"Șterge diagramă\",\n    are_you_sure_delete_diagram:\n      \"Ești sigur că vrei să ștergi această diagramă? Această operațiune este ireversibilă.\",\n    oops_smth_went_wrong: \"Oops! A apărut o problemă\",\n    import_diagram: \"Importă o diagramă\",\n    import_from_source: \"Importă din SQL\",\n    export_as: \"Exportă ca\",\n    export_source: \"Exportă SQL\",\n    models: \"Modele\",\n    exit: \"Ieșire\",\n    edit: \"Editează\",\n    undo: \"Anulează\",\n    redo: \"Refă\",\n    clear: \"Șterge\",\n    are_you_sure_clear:\n      \"Ești sigur că vrei să cureți diagramă? Aceasta operațiune este ireversibilă.\",\n    cut: \"Taie\",\n    copy: \"Copiază\",\n    paste: \"Lipește\",\n    duplicate: \"Duplica\",\n    delete: \"Șterge\",\n    copy_as_image: \"Copiază ca imagine\",\n    view: \"Vizualizează\",\n    header: \"Bară de meniu\",\n    sidebar: \"Bară laterală\",\n    issues: \"Probleme\",\n    presentation_mode: \"Mod prezentare\",\n    strict_mode: \"Mod strict\",\n    field_details: \"Detalii câmp\",\n    reset_view: \"Resetează vizualizarea\",\n    show_grid: \"Arată grilă\",\n    show_cardinality: \"Arată cardinalitatea\",\n    theme: \"Temă\",\n    light: \"Luminos\",\n    dark: \"Întunecat\",\n    zoom_in: \"Măriți\",\n    zoom_out: \"Micșora\",\n    fullscreen: \"Ecran complet\",\n    settings: \"Setări\",\n    show_timeline: \"Arată cronologia\",\n    autosave: \"Salvare automată\",\n    panning: \"Panoramare\",\n    show_debug_coordinates: \"Arată coordonatele de depanare\",\n    transform: \"Transformă\",\n    viewbox: \"Cutie de vizualizare\",\n    cursor_coordinates: \"Coordonate cursorului\",\n    coordinate_space: \"Spațiu\",\n    coordinate_space_screen: \"Ecran\",\n    coordinate_space_diagram: \"Diagramă\",\n    table_width: \"Lățimea tabelului\",\n    language: \"Limbă\",\n    flush_storage: \"Golește depozitorea\",\n    are_you_sure_flush_storage:\n      \"Esti sigur că vrei să golesți depozitorea? Aceasta va șterge ireversibil toate diagramele și modelele personalizate.\",\n    storage_flushed: \"Depozitorea a fost golită\",\n    help: \"Ajutor\",\n    shortcuts: \"Scurtături\",\n    ask_on_discord: \"Întrebați-ne pe Discord\",\n    feedback: \"Feedback\",\n    no_changes: \"Nicio modificare\",\n    loading: \"Se încarcă...\",\n    last_saved: \"Ultima salvare\",\n    saving: \"Se salvează...\",\n    failed_to_save: \"Salvarea a eșuat\",\n    fit_window_reset: \"Potrivește fereastra / Resetează\",\n    zoom: \"Zoom\",\n    add_table: \"Adaugă tabel\",\n    add_area: \"Adaugă zonă\",\n    add_note: \"Adaugă notă\",\n    add_type: \"Adaugă tip\",\n    to_do: \"De făcut\",\n    tables: \"Tabele\",\n    relationships: \"Relații\",\n    subject_areas: \"Zonă subiectelor\",\n    notes: \"Note\",\n    types: \"Tipuri\",\n    search: \"Căutare...\",\n    no_tables: \"Fără tabele\",\n    no_tables_text: \"Începe să construiești diagrama!\",\n    no_relationships: \"Fără relații\",\n    no_relationships_text: \"Trage pentru a conecta câmpuri și a forma relații!\",\n    no_subject_areas: \"Fără zone de subiecte\",\n    no_subject_areas_text: \"Adaugă zone de subiecte pentru a grupa tabelele!\",\n    no_notes: \"Fără note\",\n    no_notes_text:\n      \"Folosește notele pentru a înregistra informații suplimentare\",\n    no_types: \"Fără tipuri\",\n    no_types_text: \"Creează-ți propriile tipuri de date personalizate\",\n    no_issues: \"Nu au fost detectate probleme.\",\n    strict_mode_is_on_no_issues:\n      \"Modul strict este dezactivat, așa că nu vor fi afișate probleme.\",\n    name: \"Nume\",\n    type: \"Tip\",\n    null: \"Null\",\n    not_null: \"Nu este null\",\n    primary: \"Primar\",\n    unique: \"Unic\",\n    autoincrement: \"Increment automat\",\n    default_value: \"Implicit\",\n    check: \"Verifică expresia\",\n    this_will_appear_as_is:\n      \"*Aceasta va apărea așa cum este în scriptul generat.\",\n    comment: \"Comentariu\",\n    add_field: \"Adaugă câmp\",\n    values: \"Valori\",\n    size: \"Mărime\",\n    precision: \"Precizie\",\n    set_precision: \"Setează precizia: 'mărime, cifre'\",\n    use_for_batch_input: \"Folosește , pentru input în masă\",\n    indices: \"Indici\",\n    add_index: \"Adaugă index\",\n    select_fields: \"Selectează câmpuri\",\n    title: \"Titlu\",\n    not_set: \"Necompletat\",\n    foreign: \"Străin\",\n    cardinality: \"Cardinalitate\",\n    on_update: \"La actualizare\",\n    on_delete: \"La ștergere\",\n    swap: \"Schimbă\",\n    one_to_one: \"Unul la unul\",\n    one_to_many: \"Unul la mulți\",\n    many_to_one: \"Mulți la unul\",\n    content: \"Conținut\",\n    types_info:\n      \"Această caracteristică este destinată DBMS-urilor obiect-relaționale precum PostgreSQL.\\nDacă este folosită pentru MySQL sau MariaDB, un tip JSON va fi generat cu validarea corespunzătoare a json.\\nDacă este folosită pentru SQLite, va fi tradusă într-un BLOB.\\nDacă este folosită pentru MSSQL, va fi generat un alias de tip pentru primul câmp.\",\n    table_deleted: \"Tabel șters\",\n    area_deleted: \"Zonă ștearsă\",\n    note_deleted: \"Notă ștearsă\",\n    relationship_deleted: \"Relație ștearsă\",\n    type_deleted: \"Tip șters\",\n    cannot_connect: \"Nu se poate conecta, coloanele au tipuri diferite\",\n    copied_to_clipboard: \"Copiat în clipboard\",\n    create_new_diagram: \"Creează diagramă nouă\",\n    cancel: \"Anulează\",\n    open_diagram: \"Deschide diagrama\",\n    rename_diagram: \"Redenumește diagrama\",\n    export: \"Exportă\",\n    export_image: \"Exportă imagine\",\n    create: \"Creează\",\n    confirm: \"Confirmați\",\n    last_modified: \"Ultima modificare\",\n    drag_and_drop_files:\n      \"Trageți și plasați fișierul aici sau faceți clic pentru a încărca.\",\n    upload_sql_to_generate_diagrams:\n      \"Încărcați un fișier SQL pentru a genera automat tabelele și coloanele.\",\n    overwrite_existing_diagram: \"Suprascrie diagrama existentă\",\n    only_mysql_supported:\n      \"*Deocamdată, este acceptat doar încărcarea scripturilor MySQL.\",\n    blank: \"Gol\",\n    filename: \"Nume fișier\",\n    table_w_no_name: \"A fost declarat un tabel fără nume\",\n    duplicate_table_by_name: \"Tabel duplicat cu numele '{{tableName}}'\",\n    empty_field_name: \"Nume câmp gol `nume` în tabelul '{{tableName}}'\",\n    empty_field_type: \"Tip câmp gol `tip` în tabelul '{{tableName}}'\",\n    no_values_for_field:\n      \"'{{fieldName}}' câmp din tabelul '{{tableName}}' este de tip `{{type}}` dar nu au fost specificate valori\",\n    default_doesnt_match_type:\n      \"Valoarea implicită pentru câmpul '{{fieldName}}' din tabelul '{{tableName}}' nu se potrivește cu tipul său\",\n    not_null_is_null:\n      \"'{{fieldName}}' câmp din tabelul '{{tableName}}' NU ESTE NULL dar are valoarea implicită NULL\",\n    duplicate_fields:\n      \"Câmpuri duplicate în tabelul '{{tableName}}' cu numele '{{fieldName}}'\",\n    duplicate_index:\n      \"Index duplicat cu numele '{{indexName}}' în tabelul '{{tableName}}'\",\n    empty_index: \"Index în tabelul '{{tableName}}' nu indexează nici o coloană\",\n    no_primary_key: \"Tabelul '{{tableName}}' nu are cheie primară\",\n    type_with_no_name: \"A fost declarat un tip fără nume\",\n    duplicate_types: \"Tipuri duplicate cu numele '{{typeName}}'\",\n    type_w_no_fields: \"A fost declarat un tip gol '{{typeName}}' fără câmpuri\",\n    empty_type_field_name: \"Nume câmp gol `nume` în tipul '{{typeName}}'\",\n    empty_type_field_type: \"Tip câmp gol `tip` în tipul '{{typeName}}'\",\n    no_values_for_type_field:\n      \"'{{fieldName}}' câmp din tipul '{{typeName}}' este de tip `{{type}}` dar nu au fost specificate valori\",\n    duplicate_type_fields:\n      \"Câmpuri duplicate în tipul '{{typeName}}' cu numele '{{fieldName}}'\",\n    duplicate_reference: \"Referință duplicată cu numele '{{refName}}'\",\n    circular_dependency: \"Dependență circulară implicând tabelul '{{refName}}'\",\n    timeline: \"Cronologie\",\n    priority: \"Prioritate\",\n    none: \"Nimic\",\n    low: \"Scăzut\",\n    medium: \"Mediu\",\n    high: \"Ridicat\",\n    sort_by: \"Sortează după\",\n    my_order: \"Comanda mea\",\n    completed: \"Completat\",\n    alphabetically: \"Alfabetic\",\n    add_task: \"Adaugă sarcină\",\n    details: \"Detalii\",\n    no_tasks: \"Nu aveți sarcini încă.\",\n    no_activity: \"Nu aveți activitate încă.\",\n    move_element: \"Mută {{name}} la {{coords}}\",\n    edit_area: \"{{extra}} Editează zona {{areaName}}\",\n    delete_area: \"Șterge zona {{areaName}}\",\n    edit_note: \"{{extra}} Editează nota {{noteTitle}}\",\n    delete_note: \"Șterge nota {{noteTitle}}\",\n    edit_table: \"{{extra}} Editează tabelul {{tableName}}\",\n    delete_table: \"Șterge tabelul {{tableName}}\",\n    edit_type: \"{{extra}} Editează tipul {{typeName}}\",\n    delete_type: \"Șterge tipul {{typeName}}\",\n    add_relationship: \"Adaugă relație\",\n    edit_relationship: \"{{extra}} Editează relația {{refName}}\",\n    delete_relationship: \"Șterge relația {{refName}}\",\n    not_found: \"Nu a fost găsit\",\n    pick_db: \"Alege o bază de date\",\n    generic: \"General\",\n    generic_description:\n      \"Diagramele generale pot fi exportate în orice tip de SQL, dar susțin câteva tipuri de date.\",\n    enums: \"Enumerații\",\n    add_enum: \"Adaugă enumerație\",\n    edit_enum: \"{{extra}} Editează enumerația {{enumName}}\",\n    delete_enum: \"Șterge enumerația\",\n    enum_w_no_name: \"Enumerație găsită fără nume\",\n    enum_w_no_values: \"Enumerația '{{enumName}}' nu conține valori\",\n    duplicate_enums: \"Enumerații duplicate cu numele '{{enumName}}'\",\n    no_enums: \"Fără enumerații\",\n    no_enums_text: \"Definiți enumerații aici\",\n    declare_array: \"Declarați un array\",\n    empty_index_name:\n      \"A fost declarat un index fără nume în tabelul '{{tableName}}'\",\n    didnt_find_diagram: \"Oops! Nu am găsit diagrama.\",\n    unsigned: \"Fără semn\",\n    share: \"Împărtășește\",\n    unshare: \"Nu mai împărtăși\",\n    copy_link: \"Copiază linkul\",\n    readme: \"README\",\n    failed_to_load: \"Eșec la încărcare. Asigurați-vă că linkul este corect.\",\n    share_info:\n      \"*Împărtășirea acestui link nu va crea o sesiune de colaborare în timp real.\",\n    show_relationship_labels: \"Arată etichetele relațiilor\",\n    docs: \"Documentație\",\n  },\n};\n\nexport { ro, romanian };\n"
  },
  {
    "path": "src/i18n/locales/ru.js",
    "content": "const russian = {\n  name: \"Russian\",\n  native_name: \"Русский\",\n  code: \"ru\",\n};\n\nconst ru = {\n  translation: {\n    report_bug: \"Сообщить об ошибке\",\n    import_from: \"Импорт\",\n    import: \"Импорт\",\n    file: \"Файл\",\n    new: \"Новый\",\n    new_window: \"Новое окно\",\n    open: \"Открыть\",\n    save: \"Сохранить\",\n    save_as: \"Сохранить как\",\n    save_as_template: \"Сохранить как шаблон\",\n    template_saved: \"Шаблон сохранен!\",\n    rename: \"Переименовать\",\n    delete_diagram: \"Удалить диаграмму\",\n    are_you_sure_delete_diagram:\n      \"Вы уверены, что хотите удалить эту диаграмму? Эта операция необратима.\",\n    oops_smth_went_wrong: \"Упс! Что-то пошло не так.\",\n    import_diagram: \"Импорт диаграммы\",\n    import_from_source: \"Импорт из SQL\",\n    export_as: \"Экспорт как\",\n    export_source: \"Экспорт в SQL\",\n    models: \"Модели\",\n    exit: \"Выход\",\n    edit: \"Редактировать\",\n    undo: \"Отменить\",\n    redo: \"Повторить\",\n    clear: \"Очистить\",\n    are_you_sure_clear:\n      \"Вы уверены, что хотите очистить диаграмму? Это необратимо.\",\n    cut: \"Вырезать\",\n    copy: \"Копировать\",\n    paste: \"Вставить\",\n    duplicate: \"Дублировать\",\n    delete: \"Удалить\",\n    copy_as_image: \"Копировать как изображение\",\n    view: \"Вид\",\n    header: \"Меню\",\n    sidebar: \"Боковая панель\",\n    issues: \"Проблемы\",\n    presentation_mode: \"Режим презентации\",\n    strict_mode: \"Строгий режим\",\n    field_details: \"Подробности поля\",\n    reset_view: \"Сбросить вид\",\n    show_grid: \"Показать сетку\",\n    show_cardinality: \"Показать кардинальность\",\n    theme: \"Тема\",\n    light: \"Светлая\",\n    dark: \"Темная\",\n    zoom_in: \"Увеличить\",\n    zoom_out: \"Уменьшить\",\n    fullscreen: \"Полноэкранный режим\",\n    settings: \"Настройки\",\n    show_timeline: \"Показать временную шкалу\",\n    autosave: \"Автосохранение\",\n    panning: \"Панорамирование\",\n    table_width: \"Ширина таблицы\",\n    language: \"Язык\",\n    flush_storage: \"Очистить хранилище\",\n    are_you_sure_flush_storage:\n      \"Вы уверены, что хотите очистить хранилище? Это необратимо удалит все ваши диаграммы и пользовательские шаблоны.\",\n    storage_flushed: \"Хранилище очищено\",\n    help: \"Помощь\",\n    shortcuts: \"Горячие клавиши\",\n    ask_on_discord: \"Задайте вопрос в Discord\",\n    feedback: \"Обратная связь\",\n    no_changes: \"Нет изменений\",\n    loading: \"Загрузка...\",\n    last_saved: \"Последнее сохранение\",\n    saving: \"Сохранение...\",\n    failed_to_save: \"Не удалось сохранить\",\n    fit_window_reset: \"Подогнать к окну / Сбросить\",\n    zoom: \"Масштаб\",\n    add_table: \"Добавить таблицу\",\n    add_area: \"Добавить область\",\n    add_note: \"Добавить заметку\",\n    add_type: \"Добавить тип\",\n    to_do: \"Делать\",\n    tables: \"Таблицы\",\n    relationships: \"Отношения\",\n    subject_areas: \"Области предметной области\",\n    notes: \"Заметки\",\n    types: \"Типы\",\n    search: \"Поиск...\",\n    no_tables: \"Нет таблиц\",\n    no_tables_text: \"Начните создавать свою диаграмму!\",\n    no_relationships: \"Нет отношений\",\n    no_relationships_text:\n      \"Перетащите, чтобы соединить поля и формировать отношения!\",\n    no_subject_areas: \"Нет предметных областей\",\n    no_subject_areas_text:\n      \"Добавьте предметные области для группировки таблиц!\",\n    no_notes: \"Нет заметок\",\n    no_notes_text: \"Используйте заметки для записи дополнительной информации\",\n    no_types: \"Нет типов\",\n    no_types_text: \"Создайте собственные пользовательские типы данных\",\n    no_issues: \"Проблемы не обнаружены.\",\n    strict_mode_is_on_no_issues:\n      \"Строгий режим выключен, поэтому проблемы не будут отображаться.\",\n    name: \"Имя\",\n    type: \"Тип\",\n    null: \"Null\",\n    not_null: \"Не Null\",\n    primary: \"Первичный\",\n    unique: \"Уникальный\",\n    autoincrement: \"Автоувеличение\",\n    default_value: \"Значение по умолчанию\",\n    check: \"Проверка выражения\",\n    this_will_appear_as_is:\n      \"*Это будет отображаться в сгенерированном скрипте как есть.\",\n    comment: \"Комментарий\",\n    add_field: \"Добавить поле\",\n    values: \"значения\",\n    size: \"Размер\",\n    precision: \"Точность\",\n    set_precision: \"Установить точность: (размер, цифры)\",\n    use_for_batch_input: \"Использовать , для пакетного ввода\",\n    indices: \"Индексы\",\n    add_index: \"Добавить индекс\",\n    select_fields: \"Выберите поля\",\n    title: \"Заголовок\",\n    not_set: \"Не установлено\",\n    foreign: \"Внешний\",\n    cardinality: \"Кардинальность\",\n    on_update: \"При обновлении\",\n    on_delete: \"При удалении\",\n    swap: \"Поменять\",\n    one_to_one: \"Один к одному\",\n    one_to_many: \"Один ко многим\",\n    many_to_one: \"Многие к одному\",\n    content: \"Содержание\",\n    types_info:\n      \"Эта функция предназначена для объектно-реляционных СУБД, таких как PostgreSQL.\\nПри использовании для MySQL или MariaDB будет сгенерирован тип JSON с соответствующей проверкой json.\\nПри использовании для SQLite он будет преобразован в BLOB.\\nПри использовании для MSSQL будет сгенерирован псевдоним типа для первого поля.\",\n    table_deleted: \"Таблица удалена\",\n    area_deleted: \"Область удалена\",\n    note_deleted: \"Заметка удалена\",\n    relationship_deleted: \"Отношение удалено\",\n    type_deleted: \"Тип удален\",\n    cannot_connect: \"Невозможно подключиться, колонки имеют разные типы\",\n    copied_to_clipboard: \"Скопировано в буфер обмена\",\n    create_new_diagram: \"Создать новую диаграмму\",\n    cancel: \"Отмена\",\n    open_diagram: \"Открыть диаграмму\",\n    rename_diagram: \"Переименовать диаграмму\",\n    export: \"Экспорт\",\n    export_image: \"Экспорт изображения\",\n    create: \"Создать\",\n    confirm: \"Подтвердить\",\n    last_modified: \"Последнее изменение\",\n    drag_and_drop_files: \"Перетащите файл сюда или нажмите, чтобы загрузить.\",\n    upload_sql_to_generate_diagrams:\n      \"Загрузите файл sql для автогенерации ваших таблиц и колонок.\",\n    overwrite_existing_diagram: \"Перезаписать существующую диаграмму\",\n    only_mysql_supported:\n      \"*На данный момент поддерживается только загрузка скриптов MySQL.\",\n    blank: \"Пустой\",\n    filename: \"Имя файла\",\n    table_w_no_name: \"Объявлена таблица без названия\",\n    duplicate_table_by_name: \"Дублировать таблицу по имени '{{tableName}}'\",\n    empty_field_name: \"Пустое поле `name` в таблице '{{tableName}}'\",\n    empty_field_type: \"Пустое поле `type` в таблице '{{tableName}}'\",\n    no_values_for_field:\n      \"Поле '{{fieldName}}' таблицы '{{tableName}}' имеет тип `{{type}}`, но не указаны значения\",\n    default_doesnt_match_type:\n      \"Значение по умолчанию для поля '{{fieldName}}' в таблице '{{tableName}}' не соответствует его типу\",\n    not_null_is_null:\n      \"Поле '{{fieldName}}' таблицы '{{tableName}}' НЕ NULL, но имеет значение NULL по умолчанию\",\n    duplicate_fields:\n      \"Дублирование полей таблицы по имени '{{fieldName}}' в таблице '{{tableName}}'\",\n    duplicate_index:\n      \"Дублирование индекса по имени '{{indexName}}' в таблице '{{tableName}}'\",\n    empty_index: \"Индекс в таблице '{{tableName}}' не индексирует столбцы\",\n    no_primary_key: \"В таблице '{{tableName}}' нет первичного ключа\",\n    type_with_no_name: \"Объявлен тип без названия\",\n    duplicate_types: \"Дублирование типов по имени '{{typeName}}'\",\n    type_w_no_fields: \"Объявлен пустой тип '{{typeName}}' без полей\",\n    empty_type_field_name: \"Пустое поле `name` в типе '{{typeName}}'\",\n    empty_type_field_type: \"Пустое поле `type` в типе '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Поле '{{fieldName}}' типа '{{typeName}}' имеет тип `{{type}}`, но не указаны значения\",\n    duplicate_type_fields:\n      \"Дублирование полей типа по имени '{{fieldName}}' в типе '{{typeName}}'\",\n    duplicate_reference: \"Дублирование ссылки по имени '{{refName}}'\",\n    circular_dependency:\n      \"Циклическая зависимость, вовлекающая таблицу '{{refName}}'\",\n    timeline: \"Временная шкала\",\n    priority: \"Приоритет\",\n    none: \"Нет\",\n    low: \"Низкий\",\n    medium: \"Средний\",\n    high: \"Высокий\",\n    sort_by: \"Сортировать по\",\n    my_order: \"Мой порядок\",\n    completed: \"Завершено\",\n    alphabetically: \"По алфавиту\",\n    add_task: \"Добавить задачу\",\n    details: \"Подробности\",\n    no_tasks: \"У вас еще нет задач.\",\n    no_activity: \"У вас пока нет активности.\",\n    move_element: \"Переместить {{name}} в {{coords}}\",\n    edit_area: \"{{extra}} Редактировать область {{areaName}}\",\n    delete_area: \"Удалить область {{areaName}}\",\n    edit_note: \"{{extra}} Редактировать заметку {{noteTitle}}\",\n    delete_note: \"Удалить заметку {{noteTitle}}\",\n    edit_table: \"{{extra}} Редактировать таблицу {{tableName}}\",\n    delete_table: \"Удалить таблицу {{tableName}}\",\n    edit_type: \"{{extra}} Редактировать тип {{typeName}}\",\n    delete_type: \"Удалить тип {{typeName}}\",\n    add_relationship: \"Добавить отношение\",\n    edit_relationship: \"{{extra}} Редактировать отношение {{refName}}\",\n    delete_relationship: \"Удалить отношение {{refName}}\",\n    not_found: \"Не найдено\",\n    pick_db: \"Выберите базу данных\",\n    generic: \"Общий\",\n    generic_description:\n      \"Общие диаграммы можно экспортировать в любой вариант SQL, но они поддерживают несколько типов данных.\",\n    enums: \"Перечисления\",\n    add_enum: \"Добавить перечисление\",\n    edit_enum: \"{{extra}} Изменить перечисление {{enumName}}\",\n    delete_enum: \"Удалить перечисление\",\n    enum_w_no_name: \"Найдено перечисление без имени\",\n    enum_w_no_values:\n      \"Найдено перечисление '{{enumName}}' без каких-либо значений\",\n    duplicate_enums: \"Повторяющиеся перечисления с именем '{{enumName}}'\",\n    no_enums: \"Никаких перечислений\",\n    no_enums_text: \"Определите перечисления здесь\",\n    declare_array: \"Объявите массив\",\n    empty_index_name: \"Объявленный индекс без имени в таблице '{{tableName}}'\",\n    didnt_find_diagram: \"Упс! Не нашел диаграмму.\",\n    unsigned: \"Неподписанный\",\n    share: \"Поделиться\",\n    unshare: \"Не делиться\",\n    copy_link: \"Скопировать ссылку\",\n    readme: \"README\",\n    failed_to_load:\n      \"Не удалось загрузить. Убедитесь, что ссылка указана правильно.\",\n    share_info:\n      \"* Поделившись этой ссылкой, не будет создано сеанса совместной работы в режиме реального времени.\",\n  },\n};\n\nexport { ru, russian };\n"
  },
  {
    "path": "src/i18n/locales/sd.js",
    "content": "const sindhi = {\n  name: \"Sindhi\",\n  native_name: \"سنڌي\",\n  code: \"sd\",\n};\n\nconst sd = {\n  translation: {\n    report_bug: \"بگ رپورٽ ڪريو\",\n    import: \"درآمد ڪريو\",\n    inherits: \"وارثت ۾ حاصل ٿيل\",\n    merging_column_w_inherited_definition:\n      \"ٽيبل '{{tableName}}' ۾ '{{fieldName}}' ڪالم وارثت ۾ ملندڙ تعريف سان ضم ڪيو ويندو\",\n    import_from: \"کان درآمد ڪريو\",\n    file: \"فائل\",\n    new: \"نئون\",\n    new_window: \"نئون ونڊو\",\n    no_saved_diagrams: \"توهان وٽ محفوظ ٿيل ڊاياگرام ڪونھي\",\n    open: \"کوليو\",\n    open_recent: \"تازو کوليو\",\n    save: \"محفوظ ڪريو\",\n    save_as: \"جيئن محفوظ ڪريو\",\n    save_as_template: \"ٽيمپليٽ طور محفوظ ڪريو\",\n    template_saved: \"ٽيمپليٽ محفوظ ٿي ويو!\",\n    rename: \"نالو مٽايو\",\n    delete_diagram: \"ڊاياگرام ختم ڪريو\",\n    are_you_sure_delete_diagram:\n      \"ڇا توهان واقعي هي ڊاياگرام ختم ڪرڻ چاهيو ٿا؟ هي عمل واپس نٿو اچي.\",\n    oops_smth_went_wrong: \"اوپس! ڪجھ غلط ٿي ويو.\",\n    import_diagram: \"ڊاياگرام درآمد ڪريو\",\n    import_from_source: \"SQL کان درآمد ڪريو\",\n    export_as: \"جيئن برآمد ڪريو\",\n    export_source: \"SQL برآمد ڪريو\",\n    models: \"ماڊلز\",\n    exit: \"نڪرڻ\",\n    edit: \"ترميم ڪريو\",\n    undo: \"واپس ڪريو\",\n    redo: \"پوءِ ڪريو\",\n    clear: \"صاف ڪريو\",\n    are_you_sure_clear:\n      \"ڇا توهان واقعي ڊاياگرام صاف ڪرڻ چاهيو ٿا؟ هي واپس نٿو اچي.\",\n    cut: \"ڪٽ ڪريو\",\n    copy: \"ڪاپي ڪريو\",\n    paste: \"پيسٽ ڪريو\",\n    duplicate: \"نقل ٺاهيو\",\n    delete: \"حذف ڪريو\",\n    copy_as_image: \"تصوير طور ڪاپي ڪريو\",\n    view: \"ڏسو\",\n    header: \"مينيو بار\",\n    sidebar: \"ساڄي پاسي بار\",\n    issues: \"مسئلا\",\n    presentation_mode: \"پريزينٽيشن موڊ\",\n    strict_mode: \"سخت موڊ\",\n    field_details: \"فيلڊ جون تفصيلون\",\n    reset_view: \"ڏسڻ کي ري سيٽ ڪريو\",\n    show_grid: \"گرڊ ڏيکاريو\",\n    snap_to_grid: \"گرڊ سان جوڙيو\",\n    show_datatype: \"ڊيٽا قسم ڏيکاريو\",\n    show_cardinality: \"ڪارڊينيلٽي ڏيکاريو\",\n    theme: \"ٿيم\",\n    light: \"هلڪو\",\n    dark: \"اوندهو\",\n    zoom_in: \"زوم ان\",\n    zoom_out: \"زوم آئوٽ\",\n    fullscreen: \"فل اسڪرين\",\n    settings: \"سيٽنگز\",\n    show_timeline: \"ٽائيم لائن ڏيکاريو\",\n    autosave: \"خودڪار محفوظ ڪريو\",\n    panning: \"پيننگ\",\n    show_debug_coordinates: \"ڊيبگ ڪوآرڊينيٽس ڏيکاريو\",\n    transform: \"تبديل ڪريو\",\n    viewbox: \"ڏسڻ وارو باڪس\",\n    cursor_coordinates: \"ڪرسر ڪوآرڊينيٽس\",\n    coordinate_space: \"جڳهه\",\n    coordinate_space_screen: \"اسڪرين\",\n    coordinate_space_diagram: \"ڊاياگرام\",\n    table_width: \"ٽيبل جي ويڪر\",\n    language: \"ٻولي\",\n    flush_storage: \"اسٽوريج صاف ڪريو\",\n    are_you_sure_flush_storage:\n      \"ڇا توهان واقعي اسٽوريج صاف ڪرڻ چاهيو ٿا؟ هي توهان جا سڀ ڊاياگرام ۽ ڪسٽم ٽيمپليٽس مستقل طور ختم ڪري ڇڏيندو.\",\n    storage_flushed: \"اسٽوريج صاف ٿي وئي\",\n    help: \"مدد\",\n    shortcuts: \"شارٽ ڪٽس\",\n    ask_on_discord: \"ڊسڪارڊ تي پڇو\",\n    feedback: \"راءِ\",\n    no_changes: \"ڪو تبديلي ناهي\",\n    loading: \"لوڊ ٿي رهيو آهي...\",\n    last_saved: \"آخري محفوظ\",\n    saving: \"محفوظ ٿي رهيو آهي...\",\n    failed_to_save: \"محفوظ ڪرڻ ۾ ناڪامي\",\n    fit_window_reset: \"ونڊو جي لحاظ سان فٽ / ري سيٽ\",\n    zoom: \"زوم\",\n    add_table: \"ٽيبل شامل ڪريو\",\n    add_area: \"علائقو شامل ڪريو\",\n    add_note: \"نوٽ شامل ڪريو\",\n    add_type: \"قسم شامل ڪريو\",\n    to_do: \"ڪرڻو آهي\",\n    tables: \"ٽيبلز\",\n    relationships: \"رشتا\",\n    subject_areas: \"مضمون جا علائقا\",\n    notes: \"نوٽس\",\n    types: \"قسمون\",\n    search: \"ڳولا...\",\n    no_tables: \"ڪو ٽيبل ناهي\",\n    no_tables_text: \"پنهنجو ڊاياگرام ٺاهڻ شروع ڪريو!\",\n    no_relationships: \"ڪو رشتو ناهي\",\n    no_relationships_text: \"فيلڊس کي ڳنڍڻ لاءِ ڊريگ ڪريو ۽ رشتا ٺاهيو!\",\n    no_subject_areas: \"ڪو مضمون وارو علائقو ناهي\",\n    no_subject_areas_text: \"ٽيبلز کي گروپ ڪرڻ لاءِ مضمون جا علائقا شامل ڪريو!\",\n    no_notes: \"ڪو نوٽ ناهي\",\n    no_notes_text: \"اضافي معلومات لاءِ نوٽس استعمال ڪريو\",\n    no_types: \"ڪو قسم ناهي\",\n    no_types_text: \"پنهنجا ڪسٽم ڊيٽا قسم ٺاهيو\",\n    no_issues: \"ڪو مسئلو نه مليو.\",\n    strict_mode_is_on_no_issues: \"سخت موڊ بند آهي، تنهنڪري ڪو مسئلو نه ڏيکاريو ويندو.\",\n    name: \"نالو\",\n    type: \"قسم\",\n    null: \"NULL\",\n    not_null: \"NULL ناهي\",\n    nullable: \"NULL قبول ٿيل\",\n    primary: \"پرائمري\",\n    unique: \"يونڪ\",\n    autoincrement: \"آٽو انڪريمنٽ\",\n    default_value: \"ڊفالٽ\",\n    check: \"چيڪ اظهار\",\n    this_will_appear_as_is: \"*هي جنريٽ ٿيل اسڪرپٽ ۾ جيئن آهي تيئن ظاهر ٿيندو.\",\n    comment: \"ٽپپو\",\n    add_field: \"فيلڊ شامل ڪريو\",\n    values: \"قدرون\",\n    size: \"سائيز\",\n    precision: \"درستگي\",\n    set_precision: \"درستگي مقرر ڪريو: 'سائيز, انگ'\",\n    use_for_batch_input: \"بيچ ان پٽ لاءِ ',' استعمال ڪريو\",\n    indices: \"انڊيڪسز\",\n    add_index: \"انڊيڪس شامل ڪريو\",\n    select_fields: \"فيلڊس چونڊيو\",\n    title: \"عنوان\",\n    not_set: \"نه سيٽ ٿيل\",\n    foreign: \"پرڏيهي\",\n    cardinality: \"ڪارڊينيلٽي\",\n    on_update: \"اپڊيٽ تي\",\n    on_delete: \"ختم ڪرڻ تي\",\n    swap: \"مٽايو\",\n    one_to_one: \"هڪ کان هڪ\",\n    one_to_many: \"هڪ کان ڪيترائي\",\n    many_to_one: \"گهڻا کان هڪ\",\n    content: \"مواد\",\n    table_deleted: \"ٽيبل ختم ٿي ويو\",\n    area_deleted: \"علائقو ختم ٿيو\",\n    note_deleted: \"نوٽ ختم ڪيو\",\n    relationship_deleted: \"رشتو ختم ڪيو\",\n    type_deleted: \"قسم ختم ڪيو\",\n    cannot_connect: \"نه ٿو ڳنڍي سگھجي، ڪالمن جا قسم مختلف آهن\",\n    copied_to_clipboard: \"ڪلپ بورڊ تي ڪاپي ٿيو\",\n    create_new_diagram: \"نئون ڊاياگرام ٺاهيو\",\n    cancel: \"منسوخ ڪريو\",\n    open_diagram: \"ڊاياگرام کوليو\",\n    rename_diagram: \"ڊاياگرام جو نالو مٽايو\",\n    export: \"برآمد ڪريو\",\n    export_image: \"تصوير برآمد ڪريو\",\n    create: \"بڻايو\",\n    confirm: \"تصديق ڪريو\",\n    last_modified: \"آخري ترميم\",\n  },\n};\n\nexport { sd, sindhi };\n"
  },
  {
    "path": "src/i18n/locales/sv-se.js",
    "content": "const swedish = {\n  name: \"Swedish\",\n  native_name: \"Svenska\",\n  code: \"sv\",\n};\n\nconst sv = {\n  translation: {\n    report_bug: \"Rapportera ett fel\",\n    import_from: \"Importera\",\n    import: \"Importera\",\n    file: \"Fil\",\n    new: \"Ny\",\n    new_window: \"Nytt fönster\",\n    open: \"Öppna\",\n    save: \"Spara\",\n    save_as: \"Spara som\",\n    save_as_template: \"Spara som mall\",\n    template_saved: \"Mall sparad!\",\n    rename: \"Ändra namn\",\n    delete_diagram: \"Radera diagram\",\n    are_you_sure_delete_diagram:\n      \"Är du säker på att du vill radera diagrammet? Denna åtgärd går inte att ångra.\",\n    oops_smth_went_wrong: \"Oj! Något gick fel.\",\n    import_diagram: \"Importera diagram\",\n    import_from_source: \"Importera från SQL\",\n    export_as: \"Exportera som\",\n    export_source: \"Exportera SQL\",\n    models: \"Modeller\",\n    exit: \"Avsluta\",\n    edit: \"Redigera\",\n    undo: \"Ångra\",\n    redo: \"Gör om\",\n    clear: \"Rensa\",\n    are_you_sure_clear:\n      \"Är du säker på att du vill ta bort dina ändringar? Denna åtgärd går inte att ångra.\",\n    cut: \"Klipp ut\",\n    copy: \"Kopiera\",\n    paste: \"Klistra\",\n    duplicate: \"Duplicera\",\n    delete: \"Radera\",\n    copy_as_image: \"Kopiera som bild\",\n    view: \"Visa\",\n    header: \"Menylinje\",\n    sidebar: \"Sidopanel\",\n    issues: \"Fel\",\n    presentation_mode: \"Presentationsläge\",\n    strict_mode: \"Strikt läge\",\n    field_details: \"Fältdetaljer\",\n    reset_view: \"Återställ vy\",\n    show_grid: \"Visa rutnät\",\n    show_cardinality: \"Visa kardinalitet\",\n    theme: \"Tema\",\n    light: \"Ljust\",\n    dark: \"Mörkt\",\n    zoom_in: \"Zooma in\",\n    zoom_out: \"Zooma ut\",\n    fullscreen: \"Helskärm\",\n    settings: \"Inställningar\",\n    show_timeline: \"Visa tidslinje\",\n    autosave: \"Autospara\",\n    panning: \"Panorering\",\n    show_debug_coordinates: \"Visa felsökningskoordinater\",\n    transform: \"Transformera\",\n    viewbox: \"Visningsruta\",\n    cursor_coordinates: \"Markörkoordinater\",\n    coordinate_space: \"Koordinatsystem\",\n    coordinate_space_screen: \"Skärm\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Tabell-bredd\",\n    language: \"Språk\",\n    flush_storage: \"Töm lagring\",\n    are_you_sure_flush_storage:\n      \"Är du säker på att du vill tömma lagringen? Detta kommer radera alla dina diagram och anpassade mallar och går inte att ångra.\",\n    storage_flushed: \"Lagring tömd\",\n    help: \"Hjälp\",\n    shortcuts: \"Kortkommandon\",\n    ask_on_discord: \"Fråga oss på Discord\",\n    feedback: \"Feedback\",\n    no_changes: \"Inga ändringar\",\n    loading: \"Laddar...\",\n    last_saved: \"Senast sparad\",\n    saving: \"Sparar...\",\n    failed_to_save: \"Kunde inte spara\",\n    fit_window_reset: \"Anpassa fönster / Återställ\",\n    zoom: \"Zoom\",\n    add_table: \"Lägg till tabell\",\n    add_area: \"Lägg till område\",\n    add_note: \"Lägg till anteckning\",\n    add_type: \"Lägg till typ\",\n    to_do: \"Att göra\",\n    tables: \"Tabeller\",\n    relationships: \"Relationer\",\n    subject_areas: \"Ämnesområden\",\n    notes: \"Anteckningar\",\n    types: \"Typer\",\n    search: \"Sök...\",\n    no_tables: \"Inga tabeller\",\n    no_tables_text: \"Börja bygga ditt diagram!\",\n    no_relationships: \"Inga relationer\",\n    no_relationships_text: \"Dra för att koppla fält och skapa relationer!\",\n    no_subject_areas: \"Inga ämnesområden\",\n    no_subject_areas_text: \"Lägg till ämnesområden för att gruppera tabeller!\",\n    no_notes: \"Inga anteckningar\",\n    no_notes_text: \"Använd anteckningar för att lägga till extra information\",\n    no_types: \"Inga typer\",\n    no_types_text: \"Skapa dina egna anpassade datatyper\",\n    no_issues: \"Inga fel upptäcktes.\",\n    strict_mode_is_on_no_issues:\n      \"Strikt läge är påslaget, så inga fel kommer att visas.\",\n    name: \"Namn\",\n    type: \"Typ\",\n    null: \"Null\",\n    not_null: \"Inte null\",\n    primary: \"Primär\",\n    unique: \"Unik\",\n    autoincrement: \"Autoinkrement\",\n    default_value: \"Standardvärde\",\n    check: \"Kontrollera uttryck\",\n    this_will_appear_as_is:\n      \"*Detta kommer att visas i det genererade skriptet som det är.\",\n    comment: \"Kommentar\",\n    add_field: \"Lägg till fält\",\n    values: \"Värden\",\n    size: \"Storlek\",\n    precision: \"Precision\",\n    set_precision: \"Ställ in precision: 'storlek, siffror'\",\n    use_for_batch_input: \"Använd för batch-inmatning\",\n    indices: \"Index\",\n    add_index: \"Lägg till index\",\n    select_fields: \"Välj fält\",\n    title: \"Titel\",\n    not_set: \"Inte satt\",\n    foreign: \"Främmande\",\n    cardinality: \"Kardinalitet\",\n    on_update: \"Vid uppdatering\",\n    on_delete: \"Vid radering\",\n    swap: \"Byt\",\n    one_to_one: \"En-till-en\",\n    one_to_many: \"En-till-många\",\n    many_to_one: \"Många-till-en\",\n    content: \"Innehåll\",\n    types_info:\n      \"Denna funktion är avsedd för objekt-relationella DBMS som PostgreSQL.\\nOm avsett för MySQL eller MariaDB, kommer en JSON-typ att genereras med motsvarande JSON-valideringskontroll.\\nOm avsett för SQLite, kommer den att översättas till en BLOB.\\nOm avsett för MSSQL, kommer ett typ-alias skapas upp till det första fältet.\",\n    table_deleted: \"Tabell raderad\",\n    area_deleted: \"Område raderat\",\n    note_deleted: \"Anteckning raderad\",\n    relationship_deleted: \"Relation raderad\",\n    type_deleted: \"Typ raderad\",\n    cannot_connect: \"Kan inte ansluta, kolumnerna har olika typer\",\n    copied_to_clipboard: \"Kopierad till urklipp\",\n    create_new_diagram: \"Skapa nytt diagram\",\n    cancel: \"Avbryt\",\n    open_diagram: \"Öppna diagram\",\n    rename_diagram: \"Byt namn på diagram\",\n    export: \"Exportera\",\n    export_image: \"Exportera bild\",\n    create: \"Skapa\",\n    confirm: \"Bekräfta\",\n    last_modified: \"Senast ändrad\",\n    drag_and_drop_files:\n      \"Dra och släpp filen här eller klicka för att ladda upp.\",\n    upload_sql_to_generate_diagrams:\n      \"Ladda upp en SQL-fil för att auto-generera dina tabeller och kolumner.\",\n    overwrite_existing_diagram: \"Skriv över befintligt diagram\",\n    only_mysql_supported:\n      \"*För närvarande stöds endast uppladdning av MySQL-skript.\",\n    blank: \"Tom\",\n    filename: \"Filnamn\",\n    table_w_no_name: \"Deklarerade en tabell utan namn\",\n    duplicate_table_by_name: \"Duplicerad tabell med namnet '{{tableName}}'\",\n    empty_field_name: \"Tomt fält `namn` i tabell '{{tableName}}'\",\n    empty_field_type: \"Tomt fält `typ` i tabell '{{tableName}}'\",\n    no_values_for_field:\n      \"'{{fieldName}}'-fältet i tabellen '{{tableName}}' är av typen `{{type}}`, men inga värden är specificerade\",\n    default_doesnt_match_type:\n      \"Standardvärdet för fältet '{{fieldName}}' i tabellen '{{tableName}}' matchar inte dess typ\",\n    not_null_is_null:\n      \"'{{fieldName}}'-fältet i tabellen '{{tableName}}' är NOT NULL, men har standardvärdet NULL\",\n    duplicate_fields:\n      \"Duplicerade fält med namnet '{{fieldName}}' i tabellen '{{tableName}}'\",\n    duplicate_index:\n      \"Duplicerat index med namnet '{{indexName}}' i tabellen '{{tableName}}'\",\n    empty_index: \"Index i tabellen '{{tableName}}' indexerar inga kolumner\",\n    no_primary_key: \"Tabellen '{{tableName}}' har ingen primärnyckel\",\n    type_with_no_name: \"Deklarerade en typ utan namn\",\n    duplicate_types: \"Duplicerade typer med namnet '{{typeName}}'\",\n    type_w_no_fields: \"Deklarerade en tom typ '{{typeName}}' utan fält\",\n    empty_type_field_name: \"Tomt fält `namn` i typen '{{typeName}}'\",\n    empty_type_field_type: \"Tomt fält `typ` i typen '{{typeName}}'\",\n    no_values_for_type_field:\n      \"'{{fieldName}}'-fältet av typen '{{typeName}}' är av typen `{{type}}`, men inga värden är specificerade\",\n    duplicate_type_fields:\n      \"Duplicerade fält med namnet '{{fieldName}}' av typen '{{typeName}}'\",\n    duplicate_reference: \"Duplicerad referens med namnet '{{refName}}'\",\n    circular_dependency: \"Cirkulärt beroende gällande tabellen '{{refName}}'\",\n    timeline: \"Tidslinje\",\n    priority: \"Prioritet\",\n    none: \"Ingen\",\n    low: \"Låg\",\n    medium: \"Medel\",\n    high: \"Hög\",\n    sort_by: \"Sortera efter\",\n    my_order: \"Min ordning\",\n    completed: \"Slutförd\",\n    alphabetically: \"Alfabetiskt\",\n    add_task: \"Lägg till uppgift\",\n    details: \"Detaljer\",\n    no_tasks: \"Du har inga uppgifter ännu.\",\n    no_activity: \"Du har ingen aktivitet ännu.\",\n    move_element: \"Flytta {{name}} till {{coords}}\",\n    edit_area: \"{{extra}} Redigera område {{areaName}}\",\n    delete_area: \"Radera område {{areaName}}\",\n    edit_note: \"{{extra}} Redigera anteckning {{noteTitle}}\",\n    delete_note: \"Radera anteckning {{noteTitle}}\",\n    edit_table: \"{{extra}} Redigera tabell {{tableName}}\",\n    delete_table: \"Radera tabell {{tableName}}\",\n    edit_type: \"{{extra}} Redigera typ {{typeName}}\",\n    delete_type: \"Radera typ {{typeName}}\",\n    add_relationship: \"Lägg till relation\",\n    edit_relationship: \"{{extra}} Redigera relation {{refName}}\",\n    delete_relationship: \"Radera relation {{refName}}\",\n    not_found: \"Inte hittad\",\n    pick_db: \"Välj en databas\",\n    generic: \"Generisk\",\n    generic_description:\n      \"Generiska diagram kan exporteras till samtliga SQL-varianter, men stöder få datatyper.\",\n    enums: \"Enum\",\n    add_enum: \"Lägg till enum\",\n    edit_enum: \"{{extra}} Redigera enum {{enumName}}\",\n    delete_enum: \"Radera enum\",\n    enum_w_no_name: \"Hittade enum utan namn\",\n    enum_w_no_values: \"Hittade enum '{{enumName}}' utan värden\",\n    duplicate_enums: \"Duplicerade enum med namnet '{{enumName}}'\",\n    no_enums: \"Inga enum\",\n    no_enums_text: \"Definiera enum här\",\n    declare_array: \"Deklarera array\",\n    empty_index_name:\n      \"Deklarerade ett index utan namn i tabell '{{tableName}}'\",\n    didnt_find_diagram: \"Oj! Kunde inte hitta diagrammet.\",\n    unsigned: \"Osignerad\",\n    share: \"Dela\",\n    copy_link: \"Kopiera länk\",\n    readme: \"README\",\n    failed_to_load: \"Kunde inte ladda. Se till att länken är korrekt.\",\n    share_info:\n      \"* Att dela denna länk kommer inte att skapa en live samarbetssession.\",\n  },\n};\n\nexport { sv, swedish };\n"
  },
  {
    "path": "src/i18n/locales/sw.js",
    "content": "const swahili = {\n  name: \"Swahili\",\n  native_name: \"Kiswahili\",\n  code: \"sw\",\n};\n\nconst sw = {\n  translation: {\n    report_bug: \"Ripoti hitilafu\",\n    import_from: \"Leta kutoka\",\n    import: \"Leta\",\n    inherits: \"Inarithi\",\n    merging_column_w_inherited_definition:\n      \"Safu wima '{{fieldName}}' katika jedwali '{{tableName}}' itaunganisha ufafanuzi uliorithiwa\",\n    file: \"Faili\",\n    new: \"Mpya\",\n    new_window: \"Dirisha jipya\",\n    open: \"Fungua\",\n    open_recent: \"Fungua ya hivi karibuni\",\n    no_saved_diagrams: \"Huna mchoro uliohifadhiwa\",\n    save: \"Hifadhi\",\n    save_as: \"Hifadhi kama\",\n    save_as_template: \"Hifadhi kama kiolezo\",\n    template_saved: \"Kiolezo kimehifadhiwa!\",\n    rename: \"Badilisha jina\",\n    delete_diagram: \"Futa mchoro\",\n    are_you_sure_delete_diagram:\n      \"Una uhakika unataka kufuta mchoro huu? Hatua hii haiwezi kutenduliwa.\",\n    oops_smth_went_wrong: \"Samahani! Kuna tatizo lilitokea.\",\n    import_diagram: \"Leta mchoro\",\n    import_from_source: \"Leta kutoka SQL\",\n    export_as: \"Hamisha kama\",\n    export_source: \"Hamisha SQL\",\n    models: \"Mifano\",\n    exit: \"Ondoka\",\n    edit: \"Hariri\",\n    undo: \"Tendua\",\n    redo: \"Rudia\",\n    clear: \"Futa\",\n    are_you_sure_clear:\n      \"Una uhakika unataka kufuta mchoro huu? Hatua hii haiwezi kutenduliwa.\",\n    cut: \"Kata\",\n    copy: \"Nakili\",\n    paste: \"Bandika\",\n    duplicate: \"Rudufu\",\n    delete: \"Futa\",\n    copy_as_image: \"Nakili kama picha\",\n    view: \"Tazama\",\n    header: \"Upau wa menyu\",\n    sidebar: \"Upau wa kando\",\n    issues: \"Matatizo\",\n    presentation_mode: \"Hali ya uwasilishaji\",\n    strict_mode: \"Hali ya ukali\",\n    field_details: \"Maelezo ya uga\",\n    reset_view: \"Rejesha mtazamo\",\n    show_grid: \"Onyesha gridi\",\n    snap_to_grid: \"Ambatana na gridi\",\n    show_datatype: \"Onyesha aina ya data\",\n    show_cardinality: \"Onyesha hesabu\",\n    theme: \"Mandhari\",\n    light: \"Mwangaza\",\n    dark: \"Giza\",\n    zoom_in: \"Kuza ndani\",\n    zoom_out: \"Kuza nje\",\n    fullscreen: \"Skrini nzima\",\n    settings: \"Mipangilio\",\n    show_timeline: \"Onyesha ratiba ya wakati\",\n    autosave: \"Hifadhi kiotomatiki\",\n    panning: \"Kutembeza\",\n    show_debug_coordinates: \"Onyesha kuratibu za marekebisho\",\n    transform: \"Badilisha\",\n    viewbox: \"Sanduku la mtazamo\",\n    cursor_coordinates: \"Kuratibu za kionyeshi\",\n    coordinate_space: \"Nafasi ya kuratibu\",\n    coordinate_space_screen: \"Skrini\",\n    coordinate_space_diagram: \"Mchoro\",\n    table_width: \"Upana wa jedwali\",\n    language: \"Lugha\",\n    flush_storage: \"Safisha hifadhi\",\n    are_you_sure_flush_storage:\n      \"Una uhakika unataka kusafisha hifadhi? Hii itafuta mchoro wako wote na violezo maalum kabisa.\",\n    storage_flushed: \"Hifadhi imesafishwa\",\n    help: \"Msaada\",\n    shortcuts: \"Njia za mkato\",\n    ask_on_discord: \"Tuulize kwenye Discord\",\n    feedback: \"Maoni\",\n    no_changes: \"Hakuna mabadiliko\",\n    loading: \"Inapakia...\",\n    last_saved: \"Ilihifadhiwa mwisho\",\n    saving: \"Inahifadhi...\",\n    failed_to_save: \"Imeshindwa kuhifadhi\",\n    fit_window_reset: \"Lingana na dirisha / Rejesha\",\n    zoom: \"Kuza\",\n    add_table: \"Ongeza jedwali\",\n    add_area: \"Ongeza eneo\",\n    add_note: \"Ongeza kumbukumbu\",\n    add_type: \"Ongeza aina\",\n    to_do: \"Ya kufanya\",\n    tables: \"Majedwali\",\n    relationships: \"Mahusiano\",\n    subject_areas: \"Maeneo ya mada\",\n    notes: \"Kumbukumbu\",\n    types: \"Aina\",\n    search: \"Tafuta...\",\n    no_tables: \"Hakuna majedwali\",\n    no_tables_text: \"Anza kuunda mchoro wako!\",\n    no_relationships: \"Hakuna mahusiano\",\n    no_relationships_text: \"Buruta ili kuunganisha uga na kuunda mahusiano!\",\n    no_subject_areas: \"Hakuna maeneo ya mada\",\n    no_subject_areas_text: \"Ongeza maeneo ya mada ili kuweka majedwali pamoja!\",\n    no_notes: \"Hakuna kumbukumbu\",\n    no_notes_text: \"Tumia kumbukumbu kwa maelezo ya ziada\",\n    no_types: \"Hakuna aina\",\n    no_types_text: \"Unda aina zako maalum za data\",\n    no_issues: \"Hakuna matatizo yaliyopatikana.\",\n    strict_mode_is_on_no_issues:\n      \"Hali ya ukali imewashwa, kwa hiyo matatizo hayataonyeshwa.\",\n    name: \"Jina\",\n    type: \"Aina\",\n    null: \"Null\",\n    not_null: \"Sio null\",\n    nullable: \"Inaweza kuwa null\",\n    primary: \"Ya msingi\",\n    unique: \"Ya kipekee\",\n    autoincrement: \"Ongezeko otomatiki\",\n    default_value: \"Thamani chaguomsingi\",\n    check: \"Angalia usemi\",\n    this_will_appear_as_is:\n      \"*Hii itaonekana kama ilivyo katika hati iliyoundwa.\",\n    comment: \"Maoni\",\n    add_field: \"Ongeza uga\",\n    values: \"Thamani\",\n    size: \"Ukubwa\",\n    precision: \"Usahihi\",\n    set_precision: \"Weka usahihi: (ukubwa, nambari)\",\n    use_for_batch_input: \"Tumia kwa uingizaji wa kundi\",\n    indices: \"Vielezo\",\n    add_index: \"Ongeza kielezo\",\n    select_fields: \"Chagua uga\",\n    title: \"Kichwa\",\n    not_set: \"Haijawekwa\",\n    foreign: \"Ya kigeni\",\n    cardinality: \"Hesabu\",\n    on_update: \"Wakati wa kusasisha\",\n    on_delete: \"Wakati wa kufuta\",\n    swap: \"Badilishana\",\n    one_to_one: \"Moja kwa moja\",\n    one_to_many: \"Moja kwa wengi\",\n    many_to_one: \"Wengi kwa moja\",\n    content: \"Maudhui\",\n    types_info:\n      \"Kipengele hiki ni kwa DBMS za mahusiano ya vitu kama PostgreSQL.\\nKwa MySQL/MariaDB, aina ya JSON itazalishwa na ukaguzi wa uthibitishaji wa json.\\nKwa SQLite, itabadilishwa kuwa BLOB.\\nKwa MSSQL, jina la mbadala la aina litazalishwa kwa uga wa kwanza.\",\n    table_deleted: \"Jedwali limefutwa\",\n    area_deleted: \"Eneo limefutwa\",\n    note_deleted: \"Kumbukumbu imefutwa\",\n    relationship_deleted: \"Uhusiano umefutwa\",\n    type_deleted: \"Aina imefutwa\",\n    cannot_connect: \"Haiwezi kuunganisha — aina tofauti za safu wima\",\n    copied_to_clipboard: \"Imenakiliwa kwenye ubao wa kunakili\",\n    create_new_diagram: \"Unda mchoro mpya\",\n    cancel: \"Ghairi\",\n    open_diagram: \"Fungua mchoro\",\n    rename_diagram: \"Badilisha jina la mchoro\",\n    export: \"Hamisha\",\n    export_image: \"Hamisha picha\",\n    create: \"Unda\",\n    confirm: \"Thibitisha\",\n    last_modified: \"Ilibadilishwa mwisho\",\n    drag_and_drop_files:\n      \"Buruta na udondoshe faili hapa au bofya ili kupakia.\",\n    upload_sql_to_generate_diagrams:\n      \"Pakia faili ya SQL ili kuzalisha majedwali na safu wima zako kiotomatiki.\",\n    overwrite_existing_diagram: \"Andika juu ya mchoro uliopo\",\n    only_mysql_supported:\n      \"*Kwa sasa, hati zilizopakiwa za MySQL tu zinazunguzwa.\",\n    blank: \"Tupu\",\n    filename: \"Jina la faili\",\n    table_w_no_name: \"Jedwali limetangazwa bila jina\",\n    duplicate_table_by_name: \"Jedwali lililorudufu lenye jina '{{tableName}}'\",\n    empty_field_name: \"Jina tupu la uga katika jedwali '{{tableName}}'\",\n    empty_field_type: \"Aina tupu ya uga katika jedwali '{{tableName}}'\",\n    no_values_for_field:\n      \"Uga '{{fieldName}}' katika jedwali '{{tableName}}' una aina '{{type}}' lakini hakuna thamani zilizowekwa\",\n    default_doesnt_match_type:\n      \"Thamani chaguomsingi kwa uga '{{fieldName}}' katika jedwali '{{tableName}}' hailingani na aina yake\",\n    not_null_is_null:\n      \"Uga '{{fieldName}}' katika jedwali '{{tableName}}' umewekwa NOT NULL lakini una thamani chaguomsingi ya NULL\",\n    duplicate_fields:\n      \"Uga ziliorudufu zenye jina '{{fieldName}}' katika jedwali '{{tableName}}'\",\n    duplicate_index:\n      \"Kielezo kilicho rudufu chenye jina '{{indexName}}' katika jedwali '{{tableName}}'\",\n    empty_index:\n      \"Kielezo katika jedwali '{{tableName}}' hakina safu wima\",\n    no_primary_key: \"Jedwali '{{tableName}}' halina ufunguo wa msingi\",\n    type_with_no_name: \"Aina imetangazwa bila jina\",\n    duplicate_types: \"Aina ziliorudufu zenye jina '{{typeName}}'\",\n    type_w_no_fields: \"Aina '{{typeName}}' imetangazwa bila uga\",\n    empty_type_field_name: \"Jina tupu la uga katika aina '{{typeName}}'\",\n    empty_type_field_type: \"Aina tupu ya uga katika aina '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Uga '{{fieldName}}' katika aina '{{typeName}}' una aina '{{type}}' lakini hakuna thamani zilizowekwa\",\n    duplicate_type_fields:\n      \"Uga ziliorudufu zenye jina '{{fieldName}}' katika aina '{{typeName}}'\",\n    duplicate_reference: \"Marejeleo yaliyorudufu yenye jina '{{refName}}'\",\n    circular_dependency: \"Utegemezi wa duara katika jedwali '{{refName}}'\",\n    timeline: \"Ratiba ya wakati\",\n    priority: \"Kipaumbele\",\n    none: \"Hakuna\",\n    low: \"Chini\",\n    medium: \"Wastani\",\n    high: \"Juu\",\n    sort_by: \"Panga kwa\",\n    my_order: \"Mpangilio wangu\",\n    completed: \"Imekamilika\",\n    alphabetically: \"Kwa alfabeti\",\n    add_task: \"Ongeza kazi\",\n    details: \"Maelezo\",\n    no_tasks: \"Bado huna kazi.\",\n    no_activity: \"Bado hakuna shughuli.\",\n    move_element: \"Hamisha {{name}} kwenda {{coords}}\",\n    edit_area: \"{{extra}} Hariri eneo {{areaName}}\",\n    delete_area: \"Futa eneo {{areaName}}\",\n    edit_note: \"{{extra}} Hariri kumbukumbu {{noteTitle}}\",\n    delete_note: \"Futa kumbukumbu {{noteTitle}}\",\n    edit_table: \"{{extra}} Hariri jedwali {{tableName}}\",\n    delete_table: \"Futa jedwali {{tableName}}\",\n    edit_type: \"{{extra}} Hariri aina {{typeName}}\",\n    delete_type: \"Futa aina {{typeName}}\",\n    add_relationship: \"Ongeza uhusiano\",\n    edit_relationship: \"{{extra}} Hariri uhusiano {{refName}}\",\n    delete_relationship: \"Futa uhusiano {{refName}}\",\n    pick_db: \"Chagua hifadhidata\",\n    generic: \"Ya jumla\",\n    generic_description:\n      \"Michoro ya jumla inaweza kuhamishwa kwa lahaja yoyote ya SQL, lakini si aina zote za data zinazunguzwa.\",\n    enums: \"Enums\",\n    add_enum: \"Ongeza enum\",\n    edit_enum: \"{{extra}} Hariri enum {{enumName}}\",\n    delete_enum: \"Futa enum\",\n    enum_w_no_name: \"Enum imepatikana bila jina\",\n    enum_w_no_values: \"Hakuna thamani kwa enum '{{enumName}}'\",\n    duplicate_enums: \"Enums ziliorudufu zenye jina '{{enumName}}'\",\n    enum_deleted: \"Enum imefutwa\",\n    no_enums: \"Hakuna enums\",\n    no_enums_text: \"Eleza enums hapa\",\n    declare_array: \"Tangaza safu mlalo\",\n    empty_index_name:\n      \"Kielezo kimetangazwa bila jina katika jedwali '{{tableName}}'\",\n    didnt_find_diagram: \"Samahani! Mchoro haukupatikana.\",\n    unsigned: \"Bila ishara\",\n    share: \"Shiriki\",\n    unshare: \"Acha kushiriki\",\n    copy_link: \"Nakili kiungo\",\n    readme: \"README\",\n    failed_to_load:\n      \"Imeshindwa kupakia. Hakikisha kiungo ni sahihi.\",\n    share_info:\n      \"* Kushiriki kiungo hiki hakiundi kikao cha ushirikiano wa wakati halisi.\",\n    show_relationship_labels: \"Onyesha lebo za uhusiano\",\n    docs: \"Nyaraka\",\n    supported_types: \"Aina za faili zinazozunguzwa:\",\n    bulk_update: \"Sasisha kwa wingi\",\n    multiselect: \"Chaguo nyingi\",\n    export_saved_data: \"Hamisha data iliyohifadhiwa\",\n    dbml_view: \"Mtazamo wa DBML\",\n    tab_view: \"Mtazamo wa kichupo\",\n    label: \"Lebo\",\n    many_side_label: \"Lebo ya upande wa wengi (n)\",\n    version: \"Toleo\",\n    versions: \"Matoleo\",\n    no_saved_versions: \"Hakuna matoleo yaliyohifadhiwa\",\n    record_version: \"Rekodi toleo\",\n    commited_at: \"Ilihifadhiwa tarehe\",\n    read_only: \"Soma tu\",\n    continue: \"Endelea\",\n    restore_version: \"Rejesha toleo\",\n    restore_warning:\n      \"Kupakia toleo lingine kutaandika juu ya mabadiliko yoyote.\",\n    return_to_current: \"Rudi kwenye mchoro wa sasa\",\n    no_changes_to_record: \"Hakuna mabadiliko ya kurekodi\",\n    click_to_view: \"Bofya ili kutazama\",\n    load_more: \"Pakia zaidi\",\n    clear_cache: \"Safisha cache\",\n    cache_cleared: \"Cache imesafishwa\",\n    failed_to_record_version: \"Imeshindwa kurekodi toleo\",\n    failed_to_load_diagram: \"Imeshindwa kupakia mchoro\",\n    see_all: \"Tazama yote\",\n    insert_sql: \"Ingiza SQL\",\n    upload_file: \"Pakia faili\",\n    not_found: \"Haikupatikana\",\n  },\n};\n\nexport { sw, swahili };\n"
  },
  {
    "path": "src/i18n/locales/te.js",
    "content": "const telugu = {\n  name: \"Telugu\",\n  native_name: \"తెలుగు\",\n  code: \"te\",\n};\n\nconst te = {\n  translation: {\n    report_bug: \"బగ్ నివేదించండి\",\n    import_from: \"దిగుమతి\",\n    import: \"దిగుమతి\",\n    file: \"ఫైల్\",\n    new: \"క్రొత్త\",\n    new_window: \"క్రొత్త విండో\",\n    open: \"తెరవండి\",\n    save: \"సేవ్\",\n    save_as: \"క్రింద సేవ్\",\n    save_as_template: \"టెంప్లేట్ క్రింద సేవ్\",\n    template_saved: \"టెంప్లేట్ సేవ్ అయింది!\",\n    rename: \"పేరు మార్చండి\",\n    delete_diagram: \"డయాగ్రామ్ తొలగించండి\",\n    are_you_sure_delete_diagram:\n      \"మీరు ఈ డయాగ్రామ్ తొలగించాలని నిజంగా అనుకుంటున్నారా? ఇది తిరిగి పొందలేని చర్య.\",\n    oops_smth_went_wrong: \"అయో! ఏదో తప్పు జరిగింది.\",\n    import_diagram: \"డయాగ్రామ్ దిగుమతి\",\n    import_from_source: \"SQL నుండి దిగుమతి\",\n    export_as: \"క్రింద ఎగుమతి\",\n    export_source: \"SQL ఎగుమతి\",\n    models: \"మోడల్స్\",\n    exit: \"నిష్క్రమణ\",\n    edit: \"సవరించు\",\n    undo: \"రద్దు చేయి\",\n    redo: \"మళ్ళీ చేయి\",\n    clear: \"స్పష్టంగా\",\n    are_you_sure_clear:\n      \"మీరు ఈ డయాగ్రామ్ ఖచ్చితంగా క్లియర్ చేయాలనుకుంటున్నారా? ఇది తిరిగి పొందలేని చర్య.\",\n    cut: \"కట్ చేయండి\",\n    copy: \"కాపీ చేయండి\",\n    paste: \"పేస్ట్ చేయండి\",\n    duplicate: \"డుప్లికేట్ చేయండి\",\n    delete: \"తొలగించండి\",\n    copy_as_image: \"చిత్రం కాపీ చేయి\",\n    view: \"దృశ్యం\",\n    header: \"మెనూబార్\",\n    sidebar: \"సైడ్బార్\",\n    issues: \"సమస్యలు\",\n    presentation_mode: \"ప్రెజెంటేషన్ మోడ్\",\n    strict_mode: \"స్ట్రిక్ట్ మోడ్\",\n    field_details: \"ఫీల్డ్ వివరాలు\",\n    reset_view: \"దృశ్యం రీసెట్ చేయి\",\n    show_grid: \"గ్రిడ్ చూపించు\",\n    show_cardinality: \"కార్డినాలిటీ చూపించు\",\n    theme: \"థీమ్\",\n    light: \"కాంతి\",\n    dark: \"చీకటి\",\n    zoom_in: \"జూమ్ ఇన్ చేయండి\",\n    zoom_out: \"జూమ్ అవుట్ చేయండి\",\n    fullscreen: \"పూర్తి తెర\",\n    settings: \"సెట్టింగ్స్\",\n    show_timeline: \"టైమ్‌లైన్ చూపించు\",\n    autosave: \"ఆటోసేవ్\",\n    panning: \"ప్యానింగ్\",\n    table_width: \"పట్టిక వెడల్పు\",\n    language: \"భాష\",\n    flush_storage: \"స్టోరేజ్ క్లియర్ చేయి\",\n    are_you_sure_flush_storage:\n      \"మీరు స్టోరేజ్ ఖచ్చితంగా క్లియర్ చేయాలనుకుంటున్నారా? ఇది మీ అన్ని డయాగ్రామ్‌లు మరియు కస్టమ్ టెంప్లేట్లను తిరిగి పొందలేని విధంగా తొలగిస్తుంది.\",\n    storage_flushed: \"స్టోరేజ్ క్లియర్ చేయబడింది\",\n    help: \"సహాయం\",\n    shortcuts: \"షార్ట్‌కట్లు\",\n    ask_on_discord: \"Discord లో అడగండి\",\n    feedback: \"ఫీడ్బాక్\",\n    no_changes: \"ఏ మార్పులూ లేవు\",\n    loading: \"లోడ్ అవుతోంది...\",\n    last_saved: \"చివరిగా సేవ్ చేయబడింది\",\n    saving: \"సేవ్ అవుతోంది...\",\n    failed_to_save: \"సేవ్ చేయడంలో విఫలమైంది\",\n    fit_window_reset: \"విండోకి సరిపోయే విధంగా / రీసెట్ చేయి\",\n    zoom: \"జూమ్\",\n    add_table: \"పట్టిక చేర్చండి\",\n    add_area: \"ప్రాంతం చేర్చండి\",\n    add_note: \"గమనిక చేర్చండి\",\n    add_type: \"రకం చేర్చండి\",\n    to_do: \"చేయవలసిన\",\n    tables: \"పట్టికలు\",\n    relationships: \"సంబంధాలు\",\n    subject_areas: \"విషయ ప్రాంతాలు\",\n    notes: \"గమనికలు\",\n    types: \"రకాలు\",\n    search: \"శోధించండి...\",\n    no_tables: \"ఏ పట్టికలు లేవు\",\n    no_tables_text: \"మీ డయాగ్రామ్ ను ప్రారంభించండి!\",\n    no_relationships: \"ఏ సంబంధాలు లేవు\",\n    no_relationships_text:\n      \"ఫీల్డ్స్ కలుపుకోవడానికి డ్రాగ్ చేసి సంబంధం ఏర్పాటు చేయండి!\",\n    no_subject_areas: \"ఏ విషయ ప్రాంతాలు లేవు\",\n    no_subject_areas_text: \"పట్టికలను సమూహంగా సబ్జెక్ట్ ప్రాంతాలకు చేర్చండి!\",\n    no_notes: \"ఏ గమనికలు లేవు\",\n    no_notes_text: \"అదనపు సమాచారం రికార్డ్ చేసేందుకు గమనికలు ఉపయోగించండి\",\n    no_types: \"ఏ రకాలు లేవు\",\n    no_types_text: \"మీ సొంత కస్టమ్ డేటా రకాలను సృష్టించండి\",\n    no_issues: \"ఏ సమస్యలు లభించలేదు.\",\n    strict_mode_is_on_no_issues:\n      \"స్ట్రిక్ట్ మోడ్ ఆఫ్ లో ఉంది కాబట్టి ఏ సమస్యలు చూపించబడవు.\",\n    name: \"పేరు\",\n    type: \"రకం\",\n    null: \"Null\",\n    not_null: \"Null కాదు\",\n    primary: \"ప్రాధమిక\",\n    unique: \"అద్వితీయ\",\n    autoincrement: \"స్వీయ వృద్ధి\",\n    default_value: \"మూల్యాన్ని అప్రమేయంగా చేయి\",\n    check: \"తనిఖీ\",\n    this_will_appear_as_is:\n      \"*ఇది ఉత్పత్తి చేయబడిన స్క్రిప్ట్‌లో వంటి ప్రదర్శితం అవుతుంది.\",\n    comment: \"వ్యాఖ్య\",\n    add_field: \"ఫీల్డ్ చేర్చండి\",\n    values: \"విలువలు\",\n    size: \"పరిమాణం\",\n    precision: \"సూక్ష్మత\",\n    set_precision: \"సూక్ష్మత సెట్ చేయండి: (పరిమాణం, అంకెలు)\",\n    use_for_batch_input: \"బ్యాచ్ ఇన్‌పుట్ కోసం ఉపయోగించండి\",\n    indices: \"సూచికలు\",\n    add_index: \"సూచిక చేర్చండి\",\n    select_fields: \"ఫీల్డ్స్ ఎంచుకోండి\",\n    title: \"శీర్షిక\",\n    not_set: \"సెట్ చేయబడలేదు\",\n    foreign: \"ఫారెన్\",\n    cardinality: \"కార్డినాలిటీ\",\n    on_update: \"నవీకరణపై\",\n    on_delete: \"తొలగింపుపై\",\n    swap: \"స్వాప్ చేయండి\",\n    one_to_one: \"ఒకటి నుండి ఒకటి\",\n    one_to_many: \"ఒకటి నుండి అనేక\",\n    many_to_one: \"అనేక నుండి ఒకటి\",\n    content: \"కంటెంట్\",\n    types_info:\n      \"ఈ లక్షణం object-relational DBMS లాంటి PostgreSQL కోసం ఉంది.\\nMySQL లేదా MariaDB కోసం ఉపయోగించబడితే, సంబంధిత json చెల్లుబాటు తనిఖీతో ఒక JSON రకం ఉత్పత్తి అవుతుంది.\\nSQLite కోసం ఉపయోగించబడితే, ఇది BLOB లోకి మార్చబడుతుంది.\\nMSSQL కోసం ఉపయోగించబడితే, మొదటి ఫీల్డ్ కోసం ఒక రకం అలియాస్ ఉత్పత్తి అవుతుంది.\",\n    table_deleted: \"పట్టిక తొలగించబడింది\",\n    area_deleted: \"ప్రాంతం తొలగించబడింది\",\n    note_deleted: \"గమనిక తొలగించబడింది\",\n    relationship_deleted: \"సంబంధం తొలగించబడింది\",\n    type_deleted: \"రకం తొలగించబడింది\",\n    cannot_connect: \"కనెక్ట్ చేయలేరు, కాలమ్ రకాలు భిన్నంగా ఉన్నాయి\",\n    copied_to_clipboard: \"క్లిప్‌బోర్డ్‌కు కాపీ చేయబడింది\",\n    create_new_diagram: \"క్రొత్త డయాగ్రామ్ సృష్టించండి\",\n    cancel: \"రద్దు చేయండి\",\n    open_diagram: \"డయాగ్రామ్ తెరవండి\",\n    rename_diagram: \"డయాగ్రామ్ పేరు మార్చండి\",\n    export: \"ఎగుమతి\",\n    export_image: \"చిత్రం ఎగుమతి చేయి\",\n    create: \"సృష్టించండి\",\n    confirm: \"నిర్ధారించండి\",\n    last_modified: \"చివరిగా సవరించబడింది\",\n    drag_and_drop_files:\n      \"ఫైల్స్‌ను ఇక్కడికి లాగి వదిలివేయండి లేదా అప్‌లోడ్ చేయడానికి క్లిక్ చేయండి.\",\n    upload_sql_to_generate_diagrams:\n      \"మీ టేబుల్ మరియు కాలమ్స్‌ను స్వయంచాలకంగా ఉత్పత్తి చేయడానికి SQL ఫైల్‌ను అప్‌లోడ్ చేయండి.\",\n    overwrite_existing_diagram:\n      \"అన్నిప్రతుల మునుపటి ఆర్కెంట్ అంబి అవరు ఆర్కెదాన్ని చర్\",\n    only_mysql_supported:\n      \"*ప్రస్తుతం MySQL స్క్రిప్ట్స్ మాత్రమే లోడ్ చేయడానికి మద్దతు ఉంది.\",\n    blank: \"ఖాళీ\",\n    filename: \"ఫైల్ పేరు\",\n    table_w_no_name: \"పేరు లేకుండా పట్టికని ప్రకటించారు\",\n    duplicate_table_by_name: \"పేరుతో డుప్లికేట్ పట్టిక '{{tableName}}'\",\n    empty_field_name: \"పట్టిక '{{tableName}}' లో ఖాళీ ఫీల్డ్ `పేరు`\",\n    empty_field_type: \"పట్టిక '{{tableName}}' లో ఖాళీ ఫీల్డ్ `రకం`\",\n    no_values_for_field:\n      \"పట్టిక '{{tableName}}' లో ఫీల్డ్ '{{fieldName}}' రకం `{{type}}` కానీ విలువలు ఇవ్వబడలేదు\",\n    default_doesnt_match_type:\n      \"పట్టిక '{{table.name}}' లో ఫీల్డ్ '{{fieldName}}' యొక్క డిఫాల్ట్ విలువ రకంతో సరిపోలడం లేదు\",\n    not_null_is_null:\n      \"పట్టిక '{{tableName}}' లో ఫీల్డ్ '{{fieldName}}' యొక్క విలువ NOT NULL కానీ డిఫాల్ట్ NULL ఉంది\",\n    duplicate_fields:\n      \"పట్టిక '{{tableName}}' లో పేరుతో డుప్లికేట్ టేబుల్ ఫీల్డ్స్ '{{fieldName}}'\",\n    duplicate_index:\n      \"పట్టిక '{{tableName}}' లో పేరుతో డుప్లికేట్ ఇండెక్స్ '{{indexName}}'\",\n    empty_index: \"పట్టిక '{{tableName}}' లో ఏ కాలమ్స్ ను ఇండెక్స్ చేయదు\",\n    no_primary_key: \"పట్టిక '{{tableName}}' లో ప్రాధమిక కీ లేదు\",\n    type_with_no_name: \"పేరు లేకుండా రకాన్ని ప్రకటించారు\",\n    duplicate_types: \"పేరుతో డుప్లికేట్ రకాలు '{{typeName}}'\",\n    type_w_no_fields: \"ఫీల్డ్స్ లేకుండా రకం '{{typeName}}' ను ప్రకటించారు\",\n    empty_type_field_name: \"రకం '{{typeName}}' లో ఖాళీ ఫీల్డ్ `పేరు`\",\n    empty_type_field_type: \"రకం '{{typeName}}' లో ఖాళీ ఫీల్డ్ `రకం`\",\n    no_values_for_type_field:\n      \"రకం '{{typeName}}' లో ఫీల్డ్ '{{fieldName}}' రకం `{{type}}` కానీ విలువలు ఇవ్వబడలేదు\",\n    duplicate_type_fields:\n      \"రకం '{{typeName}}' లో పేరుతో డుప్లికేట్ రకం ఫీల్డ్స్ '{{fieldName}}'\",\n    duplicate_reference: \"పేరుతో డుప్లికేట్ రిఫరెన్స్ '{{refName}}'\",\n    circular_dependency: \"పట్టిక '{{refName}}' లో సర్క్యులర్ డిపెండెన్సీ\",\n    timeline: \"టైమ్‌లైన్\",\n    priority: \"ప్రాధాన్యత\",\n    none: \"ఏదీ లేదు\",\n    low: \"తక్కువ\",\n    medium: \"మధ్యస్థ\",\n    high: \"అధిక\",\n    sort_by: \"ద్వారా క్రమబద్ధీకరించండి\",\n    my_order: \"నా క్రమం\",\n    completed: \"పూర్తి\",\n    alphabetically: \"అక్షర క్రమంలో\",\n    add_task: \"పని చేర్చండి\",\n    details: \"వివరాలు\",\n    no_tasks: \"మీ వద్ద ఇప్పటివరకు ఏ పనులు లేవు.\",\n    no_activity: \"మీ వద్ద ఇప్పటివరకు ఏ కార్యకలాపాలు లేవు.\",\n    move_element: \"{{name}} ను {{coords}} వద్ద కదలించండి\",\n    edit_area: \"{{extra}} ప్రాంతం సవరించండి {{areaName}}\",\n    delete_area: \"ప్రాంతం తొలగించండి {{areaName}}\",\n    edit_note: \"{{extra}} గమనిక సవరించండి {{noteTitle}}\",\n    delete_note: \"గమనిక తొలగించండి {{noteTitle}}\",\n    edit_table: \"{{extra}} పట్టిక సవరించండి {{tableName}}\",\n    delete_table: \"పట్టిక తొలగించండి {{tableName}}\",\n    edit_type: \"{{extra}} రకం సవరించండి {{typeName}}\",\n    delete_type: \"రకం తొలగించండి {{typeName}}\",\n    add_relationship: \"సంబంధం చేర్చండి\",\n    edit_relationship: \"{{extra}} సంబంధం సవరించండి {{refName}}\",\n    delete_relationship: \"సంబంధం తొలగించండి {{refName}}\",\n    not_found: \"దొరకలేదు\",\n  },\n};\n\nexport { te, telugu };\n"
  },
  {
    "path": "src/i18n/locales/th.js",
    "content": "const thai = {\n  name: \"Thai\",\n  native_name: \"ไทย\",\n  code: \"th\",\n};\n\nconst th = {\n  translation: {\n    report_bug: \"รายงานข้อผิดพลาด\",\n    import: \"นำเข้า\",\n    inherits: \"สืบทอด\",\n    merging_column_w_inherited_definition:\n      \"คอลัมน์ '{{fieldName}}' ในตาราง '{{tableName}}' ที่มีคำนิยามสืบทอดจะถูกรวมเข้าด้วยกัน\",\n    import_from: \"นำเข้าจาก\",\n    file: \"ไฟล์\",\n    new: \"ใหม่\",\n    new_window: \"หน้าต่างใหม่\",\n    no_saved_diagrams: \"คุณยังไม่มีไดอะแกรมที่บันทึกไว้\",\n    open: \"เปิด\",\n    open_recent: \"เปิดล่าสุด\",\n    save: \"บันทึก\",\n    save_as: \"บันทึกเป็น\",\n    save_as_template: \"บันทึกเป็นเทมเพลต\",\n    template_saved: \"บันทึกเทมเพลตแล้ว!\",\n    rename: \"เปลี่ยนชื่อ\",\n    delete_diagram: \"ลบไดอะแกรม\",\n    are_you_sure_delete_diagram:\n      \"คุณแน่ใจหรือไม่ว่าต้องการลบไดอะแกรมนี้? การดำเนินการนี้ไม่สามารถย้อนกลับได้\",\n    oops_smth_went_wrong: \"โอ๊ะ! เกิดข้อผิดพลาดบางอย่าง\",\n    import_diagram: \"นำเข้าไดอะแกรม\",\n    import_from_source: \"นำเข้าจาก SQL\",\n    export_as: \"ส่งออกเป็น\",\n    export_source: \"ส่งออก SQL\",\n    models: \"โมเดล\",\n    exit: \"ออก\",\n    edit: \"แก้ไข\",\n    undo: \"เลิกทำ\",\n    redo: \"ทำซ้ำ\",\n    clear: \"ล้าง\",\n    are_you_sure_clear:\n      \"คุณแน่ใจหรือไม่ว่าต้องการล้างไดอะแกรม? สิ่งนี้ไม่สามารถย้อนกลับได้\",\n    cut: \"ตัด\",\n    copy: \"คัดลอก\",\n    paste: \"วาง\",\n    duplicate: \"ทำซ้ำ\",\n    delete: \"ลบ\",\n    copy_as_image: \"คัดลอกเป็นภาพ\",\n    view: \"มุมมอง\",\n    header: \"แถบเมนู\",\n    sidebar: \"แถบด้านข้าง\",\n    issues: \"ปัญหา\",\n    presentation_mode: \"โหมดนำเสนอ\",\n    strict_mode: \"โหมดเข้มงวด\",\n    field_details: \"รายละเอียดฟิลด์\",\n    reset_view: \"รีเซ็ตมุมมอง\",\n    show_grid: \"แสดงเส้นกริด\",\n    snap_to_grid: \"ยึดกับกริด\",\n    show_datatype: \"แสดงชนิดข้อมูล\",\n    show_cardinality: \"แสดงความสัมพันธ์\",\n    theme: \"ธีม\",\n    light: \"สว่าง\",\n    dark: \"มืด\",\n    zoom_in: \"ซูมเข้า\",\n    zoom_out: \"ซูมออก\",\n    fullscreen: \"เต็มจอ\",\n    settings: \"การตั้งค่า\",\n    show_timeline: \"แสดงเส้นเวลา\",\n    autosave: \"บันทึกอัตโนมัติ\",\n    panning: \"เลื่อนดู\",\n    show_debug_coordinates: \"แสดงพิกัดดีบัก\",\n    transform: \"แปลง\",\n    viewbox: \"กล่องมุมมอง\",\n    cursor_coordinates: \"พิกัดเคอร์เซอร์\",\n    coordinate_space: \"พื้นที่พิกัด\",\n    coordinate_space_screen: \"หน้าจอ\",\n    coordinate_space_diagram: \"ไดอะแกรม\",\n    table_width: \"ความกว้างของตาราง\",\n    language: \"ภาษา\",\n    flush_storage: \"ล้างข้อมูลเก็บ\",\n    are_you_sure_flush_storage:\n      \"คุณแน่ใจหรือไม่ว่าต้องการล้างที่เก็บข้อมูล? การดำเนินการนี้จะลบไดอะแกรมและเทมเพลตทั้งหมดอย่างถาวร\",\n    storage_flushed: \"ล้างข้อมูลแล้ว\",\n    help: \"ช่วยเหลือ\",\n    shortcuts: \"ทางลัด\",\n    ask_on_discord: \"ถามเราใน Discord\",\n    feedback: \"ข้อเสนอแนะ\",\n    no_changes: \"ไม่มีการเปลี่ยนแปลง\",\n    loading: \"กำลังโหลด...\",\n    last_saved: \"บันทึกล่าสุด\",\n    saving: \"กำลังบันทึก...\",\n    failed_to_save: \"บันทึกล้มเหลว\",\n    fit_window_reset: \"พอดีกับหน้าต่าง / รีเซ็ต\",\n    zoom: \"ซูม\",\n    add_table: \"เพิ่มตาราง\",\n    add_area: \"เพิ่มพื้นที่\",\n    add_note: \"เพิ่มบันทึก\",\n    add_type: \"เพิ่มชนิด\",\n    to_do: \"สิ่งที่ต้องทำ\",\n    tables: \"ตาราง\",\n    relationships: \"ความสัมพันธ์\",\n    subject_areas: \"พื้นที่หัวข้อ\",\n    notes: \"บันทึก\",\n    types: \"ชนิด\",\n    search: \"ค้นหา...\",\n    no_tables: \"ไม่มีตาราง\",\n    no_tables_text: \"เริ่มสร้างไดอะแกรมของคุณเลย!\",\n    no_relationships: \"ไม่มีความสัมพันธ์\",\n    no_relationships_text: \"ลากเพื่อเชื่อมฟิลด์และสร้างความสัมพันธ์!\",\n    no_subject_areas: \"ไม่มีพื้นที่หัวข้อ\",\n    no_subject_areas_text: \"เพิ่มพื้นที่หัวข้อเพื่อจัดกลุ่มตาราง!\",\n    no_notes: \"ไม่มีบันทึก\",\n    no_notes_text: \"ใช้บันทึกเพื่อเก็บข้อมูลเพิ่มเติม\",\n    no_types: \"ไม่มีชนิด\",\n    no_types_text: \"สร้างชนิดข้อมูลของคุณเอง\",\n    no_issues: \"ไม่พบปัญหา\",\n    strict_mode_is_on_no_issues:\n      \"โหมดเข้มงวดปิดอยู่ ดังนั้นจะไม่แสดงปัญหา\",\n    name: \"ชื่อ\",\n    type: \"ชนิด\",\n    null: \"ค่าว่าง\",\n    not_null: \"ไม่อนุญาตให้ว่าง\",\n    nullable: \"สามารถว่างได้\",\n    primary: \"คีย์หลัก\",\n    unique: \"ไม่ซ้ำ\",\n    autoincrement: \"เพิ่มอัตโนมัติ\",\n    default_value: \"ค่าเริ่มต้น\",\n    check: \"ตรวจสอบเงื่อนไข\",\n    this_will_appear_as_is: \"*สิ่งนี้จะปรากฏในสคริปต์ที่สร้างขึ้นตามเดิม\",\n    comment: \"หมายเหตุ\",\n    add_field: \"เพิ่มฟิลด์\",\n    values: \"ค่า\",\n    size: \"ขนาด\",\n    precision: \"ความละเอียด\",\n    set_precision: \"ตั้งความละเอียด: 'ขนาด, หลักทศนิยม'\",\n    use_for_batch_input: \"ใช้ , สำหรับการป้อนหลายค่า\",\n    indices: \"ดัชนี\",\n    add_index: \"เพิ่มดัชนี\",\n    select_fields: \"เลือกฟิลด์\",\n    title: \"ชื่อเรื่อง\",\n    not_set: \"ยังไม่ตั้งค่า\",\n    foreign: \"คีย์ต่างประเทศ\",\n    cardinality: \"คาร์ดินัลลิตี้\",\n    on_update: \"เมื่ออัปเดต\",\n    on_delete: \"เมื่อลบ\",\n    swap: \"สลับ\",\n    one_to_one: \"หนึ่งต่อหนึ่ง\",\n    one_to_many: \"หนึ่งต่อหลาย\",\n    many_to_one: \"หลายต่อหนึ่ง\",\n    content: \"เนื้อหา\",\n    table_deleted: \"ลบตารางแล้ว\",\n    area_deleted: \"ลบพื้นที่แล้ว\",\n    note_deleted: \"ลบบันทึกแล้ว\",\n    relationship_deleted: \"ลบความสัมพันธ์แล้ว\",\n    type_deleted: \"ลบชนิดแล้ว\",\n    cannot_connect: \"ไม่สามารถเชื่อมต่อได้ คอลัมน์มีชนิดข้อมูลต่างกัน\",\n    copied_to_clipboard: \"คัดลอกไปยังคลิปบอร์ดแล้ว\",\n    create_new_diagram: \"สร้างไดอะแกรมใหม่\",\n    cancel: \"ยกเลิก\",\n    open_diagram: \"เปิดไดอะแกรม\",\n    rename_diagram: \"เปลี่ยนชื่อไดอะแกรม\",\n    export: \"ส่งออก\",\n    export_image: \"ส่งออกเป็นภาพ\",\n    create: \"สร้าง\",\n    confirm: \"ยืนยัน\",\n    last_modified: \"แก้ไขล่าสุด\",\n    drag_and_drop_files: \"ลากและวางไฟล์ที่นี่ หรือคลิกเพื่ออัปโหลด\",\n    upload_sql_to_generate_diagrams:\n      \"อัปโหลดไฟล์ SQL เพื่อสร้างตารางและคอลัมน์อัตโนมัติ\",\n    overwrite_existing_diagram: \"เขียนทับไดอะแกรมที่มีอยู่\",\n    only_mysql_supported: \"*ขณะนี้รองรับเฉพาะสคริปต์ MySQL เท่านั้น\",\n    blank: \"ว่างเปล่า\",\n    filename: \"ชื่อไฟล์\",\n    table_w_no_name: \"ประกาศตารางโดยไม่มีชื่อ\",\n    duplicate_table_by_name: \"พบตารางชื่อซ้ำ '{{tableName}}'\",\n    empty_field_name: \"ฟิลด์ไม่มีชื่อในตาราง '{{tableName}}'\",\n    empty_field_type: \"ฟิลด์ไม่มีชนิดในตาราง '{{tableName}}'\",\n    no_primary_key: \"ตาราง '{{tableName}}' ไม่มีคีย์หลัก\",\n    timeline: \"เส้นเวลา\",\n    priority: \"ลำดับความสำคัญ\",\n    none: \"ไม่มี\",\n    low: \"ต่ำ\",\n    medium: \"ปานกลาง\",\n    high: \"สูง\",\n    sort_by: \"เรียงตาม\",\n    my_order: \"ตามลำดับของฉัน\",\n    completed: \"เสร็จสิ้น\",\n    alphabetically: \"ตามตัวอักษร\",\n    add_task: \"เพิ่มงาน\",\n    details: \"รายละเอียด\",\n    no_tasks: \"ยังไม่มีงานของคุณ\",\n    no_activity: \"ยังไม่มีกิจกรรม\",\n    move_element: \"ย้าย {{name}} ไปที่ {{coords}}\",\n    delete_table: \"ลบตาราง {{tableName}}\",\n    edit_table: \"{{extra}} แก้ไขตาราง {{tableName}}\",\n    add_relationship: \"เพิ่มความสัมพันธ์\",\n    delete_relationship: \"ลบความสัมพันธ์ {{refName}}\",\n    not_found: \"ไม่พบ\",\n    pick_db: \"เลือกฐานข้อมูล\",\n    generic: \"ทั่วไป\",\n    enums: \"อีนัม\",\n    add_enum: \"เพิ่มอีนัม\",\n    no_enums: \"ไม่มีอีนัม\",\n    declare_array: \"ประกาศอาเรย์\",\n    unsigned: \"ไม่ติดลบ\",\n    share: \"แชร์\",\n    unshare: \"ยกเลิกการแชร์\",\n    copy_link: \"คัดลอกลิงก์\",\n    readme: \"README\",\n    failed_to_load: \"โหลดไม่สำเร็จ ตรวจสอบว่าลิงก์ถูกต้อง\",\n    show_relationship_labels: \"แสดงป้ายชื่อความสัมพันธ์\",\n    docs: \"เอกสาร\",\n    supported_types: \"ประเภทไฟล์ที่รองรับ:\",\n    bulk_update: \"อัปเดตหลายรายการ\",\n    multiselect: \"เลือกหลายรายการ\",\n    export_saved_data: \"ส่งออกข้อมูลที่บันทึกไว้\",\n    dbml_view: \"มุมมอง DBML\",\n    tab_view: \"มุมมองแท็บ\",\n    label: \"ป้ายชื่อ\",\n    version: \"เวอร์ชัน\",\n    versions: \"เวอร์ชันทั้งหมด\",\n    no_saved_versions: \"ยังไม่มีเวอร์ชันที่บันทึกไว้\",\n    record_version: \"บันทึกเวอร์ชัน\",\n    commited_at: \"คอมมิตเมื่อ\",\n    read_only: \"อ่านอย่างเดียว\",\n    continue: \"ดำเนินการต่อ\",\n    restore_version: \"กู้คืนเวอร์ชัน\",\n    restore_warning: \"การโหลดเวอร์ชันอื่นจะเขียนทับการเปลี่ยนแปลงปัจจุบัน\",\n    return_to_current: \"กลับไปยังไดอะแกรมปัจจุบัน\",\n    no_changes_to_record: \"ไม่มีการเปลี่ยนแปลงที่จะบันทึก\",\n    click_to_view: \"คลิกเพื่อดู\",\n    load_more: \"โหลดเพิ่มเติม\",\n    clear_cache: \"ล้างแคช\",\n    cache_cleared: \"ล้างแคชแล้ว\",\n    failed_to_record_version: \"บันทึกเวอร์ชันล้มเหลว\",\n    failed_to_load_diagram: \"โหลดไดอะแกรมล้มเหลว\",\n    see_all: \"ดูทั้งหมด\",\n  },\n};\n\nexport { th, thai };\n"
  },
  {
    "path": "src/i18n/locales/tl.js",
    "content": "const filipino = {\n  name: \"Filipino\",\n  native_name: \"Filipino\",\n  code: \"tl\",\n};\n\nconst tl = {\n  translation: {\n    report_bug: \"I-report ang bug\",\n    import: \"I-import\",\n    inherits: \"Namamana mula sa\",\n    merging_column_w_inherited_definition:\n      \"Ang kolum na '{{fieldName}}' sa talahanayan '{{tableName}}' na may namana na depinisyon ay pagsasamahin\",\n    import_from: \"I-import mula sa\",\n    file: \"File\",\n    new: \"Bago\",\n    new_window: \"Bagong window\",\n    no_saved_diagrams: \"Wala kang naka-save na diagram\",\n    open: \"Buksan\",\n    open_recent: \"Buksan kamakailan\",\n    save: \"I-save\",\n    save_as: \"I-save bilang\",\n    save_as_template: \"I-save bilang template\",\n    template_saved: \"Nai-save ang template!\",\n    rename: \"Palitan ng pangalan\",\n    delete_diagram: \"Tanggalin ang diagram\",\n    are_you_sure_delete_diagram:\n      \"Sigurado ka bang gusto mong tanggalin ang diagram na ito? Hindi na ito maaaring ma-ibalik.\",\n    oops_smth_went_wrong: \"Naku! May nangyaring mali.\",\n    import_diagram: \"Mag-import ng diagram\",\n    import_from_source: \"Mag-import mula sa SQL\",\n    export_as: \"I-export bilang\",\n    export_source: \"I-export ang SQL\",\n    models: \"Mga modelo\",\n    exit: \"Lumabas\",\n    edit: \"I-edit\",\n    undo: \"I-undo\",\n    redo: \"I-redo\",\n    clear: \"I-clear\",\n    are_you_sure_clear:\n      \"Sigurado ka bang gusto mong i-clear ang diagram? Hindi na ito maaaring ma-ibalik.\",\n    cut: \"Gupitin\",\n    copy: \"Kopyahin\",\n    paste: \"I-paste\",\n    duplicate: \"I-duplicate\",\n    delete: \"Tanggalin\",\n    copy_as_image: \"Kopyahin bilang larawan\",\n    view: \"View\",\n    header: \"Menu Bar\",\n    sidebar: \"Sidebar\",\n    issues: \"Mga isyu\",\n    presentation_mode: \"Mode ng Presentasyon\",\n    strict_mode: \"Strict Mode\",\n    field_details: \"Detalye ng Field\",\n    reset_view: \"I-reset ang Tanawin\",\n    show_grid: \"Ipakita ang Grid\",\n    snap_to_grid: \"I-snap sa Grid\",\n    show_datatype: \"Ipakita ang Uri ng Data\",\n    show_cardinality: \"Ipakita ang Kardinalidad\",\n    theme: \"Tema\",\n    light: \"Liwanag\",\n    dark: \"Madilim\",\n    zoom_in: \"I-zoom in\",\n    zoom_out: \"I-zoom out\",\n    fullscreen: \"Buong screen\",\n    settings: \"Mga Setting\",\n    show_timeline: \"Ipakita ang Timeline\",\n    autosave: \"Awtomatikong pag-save\",\n    panning: \"Panning\",\n    show_debug_coordinates: \"Ipakita ang Debug Coordinates\",\n    transform: \"I-transform\",\n    viewbox: \"Viewbox\",\n    cursor_coordinates: \"Cursor Coordinates\",\n    coordinate_space: \"Space\",\n    coordinate_space_screen: \"Screen\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Lapad ng Talahanayan\",\n    language: \"Wika\",\n    flush_storage: \"I-flush ang Storage\",\n    are_you_sure_flush_storage:\n      \"Sigurado ka bang nais mo i-flush ang storage? Tatanggalin nito ang lahat ng iyong diagrams at custom templates nang tuluyan.\",\n    storage_flushed: \"Na-flush ang Storage\",\n    help: \"Tulong\",\n    shortcuts: \"Shortcuts\",\n    ask_on_discord: \"Magtanong sa amin sa Discord\",\n    feedback: \"Feedback\",\n    no_changes: \"Walang pagbabago\",\n    loading: \"Naglo-load...\",\n    last_saved: \"Huling na-save\",\n    saving: \"Nagse-save...\",\n    failed_to_save: \"Nabigo ang pag-save\",\n    fit_window_reset: \"I-fit / I-reset ang Window\",\n    zoom: \"Zoom\",\n    add_table: \"Magdagdag ng Talahanayan\",\n    add_area: \"Magdagdag ng Area\",\n    add_note: \"Magdagdag ng Note\",\n    add_type: \"Magdagdag ng Type\",\n    to_do: \"Gagawin\",\n    tables: \"Mga Talahanayan\",\n    relationships: \"Mga Relasyon\",\n    subject_areas: \"Subject Areas\",\n    notes: \"Mga Note\",\n    types: \"Mga Uri\",\n    search: \"Maghanap...\",\n    no_tables: \"Walang mga talahanayan\",\n    no_tables_text: \"Simulan ang paggawa ng iyong diagram!\",\n    no_relationships: \"Walang mga relasyon\",\n    no_relationships_text:\n      \"I-drag para ikonekta ang mga field at bumuo ng mga relasyon!\",\n    no_subject_areas: \"Walang subject areas\",\n    no_subject_areas_text:\n      \"Magdagdag ng subject areas para paggrupuhin ang mga talahanayan!\",\n    no_notes: \"Walang note\",\n    no_notes_text: \"Gamitin ang note para sa karagdagang impormasyon\",\n    no_types: \"Walang uri\",\n    no_types_text: \"Gumawa ng iyong sariling custom data types\",\n    no_issues: \"Walang isyu na natukoy.\",\n    strict_mode_is_on_no_issues:\n      \"Strict mode ay naka-off kaya walang isyu ang ipinapakita.\",\n    name: \"Pangalan\",\n    type: \"Type\",\n    null: \"Null\",\n    not_null: \"Hindi null\",\n    nullable: \"Puwedeng null\",\n    primary: \"Primary\",\n    unique: \"Natatangi\",\n    autoincrement: \"Auto-increment\",\n    default_value: \"Default Value\",\n    check: \"Check Expression\",\n    this_will_appear_as_is: \"*Ito ay lilitaw as-is sa generated script.\",\n    comment: \"Komento\",\n    add_field: \"Magdagdag ng Field\",\n    values: \"Mga Value\",\n    size: \"Laki\",\n    precision: \"Precision\",\n    set_precision: \"Itakda ang precision: 'size, decimals'\",\n    use_for_batch_input: \"Gamitin , para sa batch input\",\n    indices: \"Mga Index\",\n    add_index: \"Magdagdag ng Index\",\n    select_fields: \"Pumili ng Fields\",\n    title: \"Pamagat\",\n    not_set: \"Hindi nakatakda\",\n    foreign: \"Foreign\",\n    cardinality: \"Kardinalidad\",\n    on_update: \"Sa update\",\n    on_delete: \"Sa pagtanggal\",\n    swap: \"Palitan\",\n    one_to_one: \"Isa-sa-isa\",\n    one_to_many: \"Isa-sa-marami\",\n    many_to_one: \"Marami-sa-isa\",\n    content: \"Nilalaman\",\n  },\n};\n\nexport { tl, filipino };\n"
  },
  {
    "path": "src/i18n/locales/tm.js",
    "content": "const tamil = {\n  name: \"Tamil\",\n  native_name: \"தமிழ்\",\n  code: \"tm\",\n};\n\nconst tm = {\n  translation: {\n    report_bug: \"பிழையை புகாரளி\",\n    import: \"இறக்குமதி\",\n    inherits: \"பரம்பரையாகப் பெறுகிறது\",\n    merging_column_w_inherited_definition:\n      \"'{{tableName}}' அட்டவணையில் '{{fieldName}}' நெடுவரிசை பரம்பரையாக வரையறுக்கப்பட்டதால் இணைக்கப்படும்\",\n    import_from: \"இதிலிருந்து இறக்குமதி\",\n    file: \"கோப்பு\",\n    new: \"புதிய\",\n    new_window: \"புதிய சாளரம்\",\n    no_saved_diagrams: \"நீங்கள் சேமித்த வரைபடங்கள் எதுவும் இல்லை\",\n    open: \"திற\",\n    open_recent: \"அண்மையில் திறந்தவை\",\n    save: \"சேமி\",\n    save_as: \"இப்படி சேமி\",\n    save_as_template: \"வார்ப்புருவாக சேமி\",\n    template_saved: \"வார்ப்புரு சேமிக்கப்பட்டது!\",\n    rename: \"மறுபெயரிடு\",\n    delete_diagram: \"வரைபடத்தை நீக்கு\",\n    are_you_sure_delete_diagram:\n      \"இந்த வரைபடத்தை நிச்சயமாக நீக்க வேண்டுமா? இந்த செயல் மாற்ற முடியாதது.\",\n    oops_smth_went_wrong: \"அய்யோ! ஏதோ தவறு ஏற்பட்டுள்ளது.\",\n    import_diagram: \"வரைபடத்தை இறக்குமதி செய்\",\n    import_from_source: \"SQL இலிருந்து இறக்குமதி செய்\",\n    export_as: \"இவ்வாறு ஏற்றுமதி செய்\",\n    export_source: \"SQL ஏற்றுமதி செய்\",\n    models: \"மாதிரிகள்\",\n    exit: \"வெளியேறு\",\n    edit: \"திருத்து\",\n    undo: \"செயல்தவிர்\",\n    redo: \"மீண்டும் செய்\",\n    clear: \"அழி\",\n    are_you_sure_clear:\n      \"வரைபடத்தை அழிக்க வேண்டுமா? இது மாற்ற முடியாதது.\",\n    cut: \"வெட்டு\",\n    copy: \"நகலெடு\",\n    paste: \"ஒட்டு\",\n    duplicate: \"நகலி\",\n    delete: \"நீக்கு\",\n    copy_as_image: \"படமாக நகலெடு\",\n    view: \"காட்சி\",\n    header: \"மெனுபார்\",\n    sidebar: \"பக்கப்பட்டி\",\n    issues: \"சிக்கல்கள்\",\n    presentation_mode: \"விளக்கக்காட்சி நிலை\",\n    strict_mode: \"கண்டிப்பான நிலை\",\n    field_details: \"புல விவரங்கள்\",\n    reset_view: \"காட்சியை மீட்டமை\",\n    show_grid: \"கட்டத்தை காட்டு\",\n    snap_to_grid: \"கட்டத்துக்கு ஒட்டி\",\n    show_datatype: \"தரவு வகையைக் காட்டு\",\n    show_cardinality: \"எண்ணிக்கையைக் காட்டு\",\n    theme: \"தீம்\",\n    light: \"வெளிச்சம்\",\n    dark: \"இருள்\",\n    zoom_in: \"பெரிதாக்கு\",\n    zoom_out: \"சிறிதாக்கு\",\n    fullscreen: \"முழுத்திரை\",\n    settings: \"அமைப்புகள்\",\n    show_timeline: \"காலவரிசையைக் காட்டு\",\n    autosave: \"தானியங்கி சேமிப்பு\",\n    panning: \"நகர்த்துதல்\",\n    show_debug_coordinates: \"வழுநீக்க இடமேற்பாட்டைக் காட்டு\",\n    transform: \"மாற்று\",\n    viewbox: \"காட்சி பெட்டி\",\n    cursor_coordinates: \"சுட்டி இடமேற்பாடு\",\n    coordinate_space: \"இடம்\",\n    coordinate_space_screen: \"திரை\",\n    coordinate_space_diagram: \"வரைபடம்\",\n    table_width: \"அட்டவணை அகலம்\",\n    language: \"மொழி\",\n    flush_storage: \"சேமிப்பகத்தை காலி செய்\",\n    are_you_sure_flush_storage:\n      \"சேமிப்பகத்தை காலி செய்ய வேண்டுமா? இது அனைத்து வரைபடங்களையும் வார்ப்புருக்களையும் நிரந்தரமாக நீக்கும்.\",\n    storage_flushed: \"சேமிப்பகம் காலி செய்யப்பட்டது\",\n    help: \"உதவி\",\n    shortcuts: \"குறுக்குவழிகள்\",\n    ask_on_discord: \"டிஸ்கார்டில் கேளுங்கள்\",\n    feedback: \"கருத்து\",\n    no_changes: \"மாற்றங்கள் இல்லை\",\n    loading: \"ஏற்றுகிறது...\",\n    last_saved: \"கடைசியாக சேமிக்கப்பட்டது\",\n    saving: \"சேமிக்கிறது...\",\n    failed_to_save: \"சேமிக்க முடியவில்லை\",\n    fit_window_reset: \"சாளரத்துக்கு பொருத்து / மீட்டமை\",\n    zoom: \"அளவு மாற்று\",\n    add_table: \"அட்டவணை சேர்\",\n    add_area: \"பகுதி சேர்\",\n    add_note: \"குறிப்பு சேர்\",\n    add_type: \"வகை சேர்\",\n    to_do: \"செய்ய வேண்டியவை\",\n    tables: \"அட்டவணைகள்\",\n    relationships: \"உறவுகள்\",\n    subject_areas: \"பொருள் பகுதிகள்\",\n    notes: \"குறிப்புகள்\",\n    types: \"வகைகள்\",\n    search: \"தேடு...\",\n    no_tables: \"அட்டவணைகள் இல்லை\",\n    no_tables_text: \"உங்கள் வரைபடத்தை உருவாக்கத் தொடங்குங்கள்!\",\n    no_relationships: \"உறவுகள் இல்லை\",\n    no_relationships_text: \"புலங்களை இணைக்க இழுத்து உறவுகளை உருவாக்குங்கள்!\",\n    no_subject_areas: \"பொருள் பகுதிகள் இல்லை\",\n    no_subject_areas_text: \"அட்டவணைகளை குழுவாக்க பொருள் பகுதிகளைச் சேர்க்கவும்!\",\n    no_notes: \"குறிப்புகள் இல்லை\",\n    no_notes_text: \"கூடுதல் தகவல்களைப் பதிவுசெய்ய குறிப்புகளை பயன்படுத்துங்கள்\",\n    no_types: \"வகைகள் இல்லை\",\n    no_types_text: \"உங்கள் தனிப்பயன் தரவு வகைகளை உருவாக்குங்கள்\",\n    no_issues: \"எந்த சிக்கல்களும் இல்லை.\",\n    strict_mode_is_on_no_issues:\n      \"கண்டிப்பான நிலை அணைக்கப்பட்டுள்ளது, எனவே சிக்கல்கள் காட்டப்படாது.\",\n    name: \"பெயர்\",\n    type: \"வகை\",\n    null: \"பூஜ்ஜியம்\",\n    not_null: \"பூஜ்ஜியம் அல்ல\",\n    nullable: \"காலியாக அனுமதிக்கப்படும்\",\n    primary: \"முதன்மை\",\n    unique: \"தனித்துவம்\",\n    autoincrement: \"தானாக அதிகரிப்பு\",\n    default_value: \"இயல்புநிலை\",\n    check: \"சரிபார்ப்பு வெளிப்பாடு\",\n    this_will_appear_as_is: \"*இது உருவாக்கப்படும் ஸ்கிரிப்டில் அப்படியே தோன்றும்.\",\n    comment: \"கருத்து\",\n    add_field: \"புலம் சேர்\",\n    values: \"மதிப்புகள்\",\n    size: \"அளவு\",\n    precision: \"துல்லியம்\",\n    set_precision: \"துல்லியத்தை அமைக்க: 'அளவு, இலக்கங்கள்'\",\n    use_for_batch_input: \"தொகுதி உள்ளீட்டிற்கு , ஐ பயன்படுத்துங்கள்\",\n    indices: \"குறியீடுகள்\",\n    add_index: \"குறியீடு சேர்\",\n    select_fields: \"புலங்களைத் தேர்ந்தெடுக்கவும்\",\n    title: \"தலைப்பு\",\n    not_set: \"அமைக்கப்படவில்லை\",\n    foreign: \"அயல்\",\n    cardinality: \"எண்ணிக்கை\",\n    on_update: \"புதுப்பிக்கும்போது\",\n    on_delete: \"நீக்கும்போது\",\n    swap: \"மாற்று\",\n    one_to_one: \"ஒன்று - ஒன்று\",\n    one_to_many: \"ஒன்று - பல\",\n    many_to_one: \"பல - ஒன்று\",\n    content: \"உள்ளடக்கம்\",\n    types_info:\n      \"இந்த அம்சம் PostgreSQL போன்ற object-relational DBMS களுக்கானது.\\nMySQL அல்லது MariaDB க்கு பயன்படுத்தினால் JSON மற்றும் json சரிபார்ப்பு உருவாக்கப்படும்.\\nSQLite க்கு பயன்படுத்தினால் BLOB ஆக மாறும்.\\nMSSQL க்கு பயன்படுத்தினால் முதல் புலத்திற்கு type alias உருவாகும்.\",\n    table_deleted: \"அட்டவணை நீக்கப்பட்டது\",\n    area_deleted: \"பகுதி நீக்கப்பட்டது\",\n    note_deleted: \"குறிப்பு நீக்கப்பட்டது\",\n    relationship_deleted: \"உறவு நீக்கப்பட்டது\",\n    type_deleted: \"வகை நீக்கப்பட்டது\",\n    cannot_connect: \"இணைக்க முடியாது, புல வகைகள் பொருந்தவில்லை\",\n    copied_to_clipboard: \"கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது\",\n    create_new_diagram: \"புதிய வரைபடத்தை உருவாக்கு\",\n    cancel: \"ரத்து செய்\",\n    open_diagram: \"வரைபடத்தைத் திற\",\n    rename_diagram: \"வரைபடத்தை மறுபெயரிடு\",\n    export: \"ஏற்றுமதி\",\n    export_image: \"படத்தை ஏற்றுமதி செய்\",\n    create: \"உருவாக்கு\",\n    confirm: \"உறுதிப்படுத்து\",\n    last_modified: \"கடைசியாக மாற்றப்பட்டது\",\n    drag_and_drop_files:\n      \"கோப்பை இங்கே இழுத்து விடவும் அல்லது கிளிக் செய்து பதிவேற்றவும்.\",\n    upload_sql_to_generate_diagrams:\n      \"அட்டவணைகள் மற்றும் புலங்களை தானாக உருவாக்க SQL கோப்பை பதிவேற்றவும்.\",\n    overwrite_existing_diagram: \"ஏற்கனவே உள்ள வரைபடத்தை மேலெழுது\",\n    only_mysql_supported:\n      \"*இப்போது MySQL ஸ்கிரிப்ட் ஏற்றுதலே ஆதரிக்கப்படுகிறது.\",\n    blank: \"வெற்று\",\n    filename: \"கோப்புப் பெயர்\",\n    table_w_no_name: \"பெயர் இல்லாத அட்டவணை அறிவிக்கப்பட்டது\",\n    duplicate_table_by_name:\n      \"'{{tableName}}' என்ற பெயரில் நகல் அட்டவணை\",\n    empty_field_name:\n      \"'{{tableName}}' அட்டவணையில் `name` புலம் வெறுமையாக உள்ளது\",\n    empty_field_type:\n      \"'{{tableName}}' அட்டவணையில் `type` புலம் வெறுமையாக உள்ளது\",\n    no_values_for_field:\n      \"'{{tableName}}' அட்டவணையின் '{{fieldName}}' புலம் `{{type}}` வகையைக் கொண்டுள்ளது, ஆனால் மதிப்புகள் இல்லை\",\n    default_doesnt_match_type:\n      \"'{{tableName}}' அட்டவணையில் '{{fieldName}}' இயல்புநிலை மதிப்பு அதன் வகைக்கு பொருந்தவில்லை\",\n    not_null_is_null:\n      \"'{{tableName}}' அட்டவணையில் '{{fieldName}}' NOT NULL ஆனால் இயல்புநிலை NULL\",\n    duplicate_fields:\n      \"'{{tableName}}' அட்டவணையில் '{{fieldName}}' என்ற நகல் புலங்கள்\",\n    duplicate_index:\n      \"'{{tableName}}' அட்டவணையில் '{{indexName}}' என்ற நகல் குறியீடு\",\n    empty_index:\n      \"'{{tableName}}' அட்டவணையில் குறியீடு எந்த நெடுவரிசைகளையும் குறியிடவில்லை\",\n    no_primary_key:\n      \"'{{tableName}}' அட்டவணையில் முதன்மை விசை இல்லை\",\n    type_with_no_name: \"பெயர் இல்லாத வகை அறிவிக்கப்பட்டது\",\n    duplicate_types: \"'{{typeName}}' என்ற நகல் வகைகள்\",\n    type_w_no_fields:\n      \"'{{typeName}}' வகையில் புலங்கள் எதுவும் இல்லை\",\n    empty_type_field_name:\n      \"'{{typeName}}' வகையில் `name` புலம் வெறுமையாக உள்ளது\",\n    empty_type_field_type:\n      \"'{{typeName}}' வகையில் `type` புலம் வெறுமையாக உள்ளது\",\n    no_values_for_type_field:\n      \"'{{typeName}}' வகையின் '{{fieldName}}' `{{type}}` வகை, ஆனால் மதிப்புகள் இல்லை\",\n    duplicate_type_fields:\n      \"'{{typeName}}' வகையில் '{{fieldName}}' என்ற நகல் புலங்கள்\",\n    duplicate_reference:\n      \"'{{refName}}' என்ற நகல் குறிப்பு\",\n    circular_dependency:\n      \"'{{refName}}' அட்டவணையை உள்ளடக்கிய வட்ட சார்பு\",\n    timeline: \"காலவரிசை\",\n    priority: \"முன்னுரிமை\",\n    none: \"எதுவுமில்லை\",\n    low: \"குறைந்த\",\n    medium: \"நடுத்தர\",\n    high: \"உயர்\",\n    sort_by: \"வரிசைப்படுத்து\",\n    my_order: \"எனது வரிசை\",\n    completed: \"முடிந்தது\",\n    alphabetically: \"அகரவரிசை\",\n    add_task: \"பணி சேர்\",\n    details: \"விவரங்கள்\",\n    no_tasks: \"பணிகள் இல்லை.\",\n    no_activity: \"செயல்பாடுகள் இல்லை.\",\n    move_element: \"{{name}} ஐ {{coords}} க்கு நகர்த்து\",\n    edit_area: \"{{extra}} {{areaName}} பகுதியைத் திருத்து\",\n    delete_area: \"{{areaName}} பகுதியை நீக்கு\",\n    edit_note: \"{{extra}} {{noteTitle}} குறிப்பைத் திருத்து\",\n    delete_note: \"{{noteTitle}} குறிப்பை நீக்கு\",\n    edit_table: \"{{extra}} {{tableName}} அட்டவணையைத் திருத்து\",\n    delete_table: \"{{tableName}} அட்டவணையை நீக்கு\",\n    edit_type: \"{{extra}} {{typeName}} வகையைத் திருத்து\",\n    delete_type: \"{{typeName}} வகையை நீக்கு\",\n    add_relationship: \"உறவு சேர்\",\n    edit_relationship:\n      \"{{extra}} {{refName}} உறவைத் திருத்து\",\n    delete_relationship:\n      \"{{refName}} உறவை நீக்கு\",\n    not_found: \"காணப்படவில்லை\",\n    pick_db: \"தரவுத்தளத்தைத் தேர்ந்தெடு\",\n    generic: \"பொதுவான\",\n    generic_description:\n      \"பொதுவான வரைபடங்கள் எந்த SQL வடிவத்திற்கும் ஏற்றுமதி செய்யப்படும் ஆனால் சில தரவு வகைகளையே ஆதரிக்கும்.\",\n    enums: \"எண்ணல்கள்\",\n    add_enum: \"எண்ணல் சேர்\",\n    edit_enum: \"{{extra}} {{enumName}} எண்ணலைத் திருத்து\",\n    delete_enum: \"எண்ணலை நீக்கு\",\n    enum_w_no_name: \"பெயர் இல்லாத எண்ணல் கண்டறியப்பட்டது\",\n    enum_w_no_values:\n      \"'{{enumName}}' எண்ணலுக்கு மதிப்புகள் இல்லை\",\n    duplicate_enums:\n      \"'{{enumName}}' என்ற நகல் எண்ணல்கள்\",\n    enum_deleted: \"எண்ணல் நீக்கப்பட்டது\",\n    no_enums: \"எண்ணல்கள் இல்லை\",\n    no_enums_text: \"எண்ணல்களை இங்கே சேர்க்கவும்\",\n    declare_array: \"அணியை அறிவி\",\n    empty_index_name:\n      \"'{{tableName}}' அட்டவணையில் பெயர் இல்லாத குறியீடு\",\n    didnt_find_diagram: \"வரைபடம் கிடைக்கவில்லை.\",\n    unsigned: \"குறியற்ற\",\n    share: \"பகிர்\",\n    unshare: \"பகிர்வை நிறுத்து\",\n    copy_link: \"இணைப்பை நகலெடு\",\n    readme: \"README\",\n    failed_to_load:\n      \"ஏற்ற முடியவில்லை. இணைப்பு சரியானதா என சரிபார்க்கவும்.\",\n    share_info:\n      \"* இந்த இணைப்பைப் பகிர்வது நேரடி ஒத்துழைப்பு அமர்வை உருவாக்காது.\",\n    show_relationship_labels:\n      \"உறவு லேபிள்களை காட்டு\",\n    docs: \"ஆவணங்கள்\",\n    supported_types: \"ஆதரிக்கப்படும் கோப்பு வகைகள்:\",\n    bulk_update: \"மொத்த புதுப்பிப்பு\",\n    multiselect: \"பல தேர்வு\",\n    export_saved_data: \"சேமித்த தரவை ஏற்றுமதி செய்\",\n    dbml_view: \"DBML காட்சி\",\n    tab_view: \"தாவல் காட்சி\",\n    label: \"லேபிள்\",\n    many_side_label: \"Many(n) பக்க லேபிள்\",\n    version: \"பதிப்பு\",\n    versions: \"பதிப்புகள்\",\n    no_saved_versions: \"பதிப்புகள் இல்லை\",\n    record_version: \"பதிப்பை பதிவு செய்\",\n    commited_at: \"செயல்படுத்திய நேரம்\",\n    read_only: \"வாசிக்க மட்டும்\",\n    continue: \"தொடரு\",\n    restore_version: \"பதிப்பை மீட்டெடு\",\n    restore_warning:\n      \"வேறு பதிப்பை ஏற்றினால் மாற்றங்கள் மேலெழுதப்படும்.\",\n    return_to_current: \"வரைபடத்திற்குத் திரும்பு\",\n    no_changes_to_record: \"பதிவு செய்ய மாற்றங்கள் இல்லை\",\n    click_to_view: \"காண கிளிக் செய்யவும்\",\n    load_more: \"மேலும் ஏற்று\",\n    clear_cache: \"கேஷை அழி\",\n    cache_cleared: \"கேஷ் அழிக்கப்பட்டது\",\n    failed_to_record_version:\n      \"பதிப்பு பதிவு செய்ய முடியவில்லை\",\n    failed_to_load_diagram:\n      \"வரைபடத்தை ஏற்ற முடியவில்லை\",\n    see_all: \"அனைத்தையும் காண்க\",\n    insert_sql: \"SQL செருகு\",\n    upload_file: \"கோப்பு பதிவேற்று\"\n  },\n};\n\nexport { tm, tamil };\n"
  },
  {
    "path": "src/i18n/locales/tr.js",
    "content": "const turkish = {\n  name: \"Turkish\",\n  native_name: \"Türkçe\",\n  code: \"tr\",\n};\n\nconst tr = {\n  translation: {\n    report_bug: \"Hata bildir\",\n    import_from: \"İçe aktar\",\n    import: \"İçe aktar\",\n    file: \"Dosya\",\n    new: \"Yeni\",\n    new_window: \"Yeni pencere\",\n    open: \"Aç\",\n    save: \"Kaydet\",\n    save_as: \"Farklı kaydet\",\n    save_as_template: \"Şablon olarak kaydet\",\n    template_saved: \"Şablon kaydedildi\",\n    rename: \"Yeniden adlandır\",\n    delete_diagram: \"Diagramı sil\",\n    are_you_sure_delete_diagram:\n      \"Diagramı silmek istediğinizden emin misiniz? Bu işlem geri döndürülemez.\",\n    oops_smth_went_wrong: \"Oops! Bir şeyler yanlış gitti.\",\n    import_diagram: \"Diagramı içe aktar\",\n    import_from_source: \"SQL dosyasından içe aktar\",\n    export_as: \"Dışa aktar\",\n    export_source: \"SQL dosyası olarak dışa aktar\",\n    models: \"Modeller\",\n    exit: \"Çıkış\",\n    edit: \"Düzenle\",\n    undo: \"Geri al\",\n    redo: \"İleri al\",\n    clear: \"Temizle\",\n    are_you_sure_clear:\n      \"Diagramı temizlemek istediğinizden emin misiniz? Bu işlem geri döndürülemez\",\n    cut: \"Kes\",\n    copy: \"Kopyala\",\n    paste: \"Yapıştır\",\n    duplicate: \"Çoğalt\",\n    delete: \"Sil\",\n    copy_as_image: \"Resim olarak kopyala\",\n    view: \"Görünüm\",\n    header: \"Menü çubuğu\",\n    sidebar: \"Kenar çubuğu\",\n    issues: \"Sorunlar\",\n    presentation_mode: \"Sunum modu\",\n    strict_mode: \"Sabit mod\",\n    field_details: \"Alan detayları\",\n    reset_view: \"Görünümü sıfırla\",\n    show_grid: \"Izgarayı göster\",\n    show_cardinality: \"Nicelikleri göster\",\n    theme: \"Tema\",\n    light: \"Açık\",\n    dark: \"Koyu\",\n    zoom_in: \"Yakınlaştır\",\n    zoom_out: \"Uzaklaştır\",\n    fullscreen: \"Tam ekran\",\n    settings: \"Ayarlar\",\n    show_timeline: \"Zaman çizelgesini göster\",\n    autosave: \"Otomatik kaydet\",\n    panning: \"Yatay kaydırma\",\n    show_debug_coordinates: \"Hata ayıklama koordinatlarını göster\",\n    transform: \"Dönüştür\",\n    viewbox: \"Görünüm kutusu\",\n    cursor_coordinates: \"İmleç koordinatları\",\n    coordinate_space: \"Koordinat uzayı\",\n    coordinate_space_screen: \"Ekran\",\n    coordinate_space_diagram: \"Diagram\",\n    table_width: \"Tablo genişliği\",\n    language: \"Dil\",\n    flush_storage: \"Depoyu temizle\",\n    are_you_sure_flush_storage:\n      \"Depoyu temizlemek istediğinizden emin misiniz? Bu işlem geri döndürülemez.\",\n    storage_flushed: \"Depo temizlendi\",\n    help: \"Yardım\",\n    shortcuts: \"Kısayollar\",\n    ask_on_discord: \"Discord'da sor\",\n    feedback: \"Geribildirim\",\n    no_changes: \"Değişiklik yok\",\n    loading: \"Yükleniyor...\",\n    last_saved: \"Son kaydedilen\",\n    saving: \"Kaydediliyor...\",\n    failed_to_save: \"Kaydetme başarısız oldu\",\n    fit_window_reset: \"Pencere sığdırma & Sıfırla\",\n    zoom: \"Yakınlaştırma\",\n    add_table: \"Tablo ekle\",\n    add_area: \"Alan ekle\",\n    add_note: \"Not ekle\",\n    add_type: \"Tip ekle\",\n    to_do: \"Yapılacaklar\",\n    tables: \"Tablolar\",\n    relationships: \"İlişkiler\",\n    subject_areas: \"Konu alanları\",\n    notes: \"Notlar\",\n    types: \"Tipler\",\n    search: \"Ara...\",\n    no_tables: \"Tablo yok\",\n    no_tables_text: \"Diagram oluşturmaya başlayın\",\n    no_relationships: \"İlişki yok\",\n    no_relationships_text:\n      \"Alanları bağlamak ve ilişkiler oluşturmak için sürükleyin\",\n    no_subject_areas: \"Konu alanı yok\",\n    no_subject_areas_text: \"Grup tablolarına konu alanları ekleyin!\",\n    no_notes: \"Not yok\",\n    no_notes_text: \"Ekstra bilgi kaydetmek için notları kullanın\",\n    no_types: \"Tip yok\",\n    no_types_text: \"Kendi özel veri türlerinizi tanımlayın\",\n    no_issues: \"Hiçbir sorun bulunamadı\",\n    strict_mode_is_on_no_issues: \"Sabit mod açık iken hatalar görüntülenmez\",\n    name: \"\",\n    type: \"Tip\",\n    null: \"Boş\",\n    not_null: \"Boş değil\",\n    primary: \"Birincil\",\n    unique: \"Benzersiz\",\n    autoincrement: \"Otomatik artan\",\n    default_value: \"Varsayılan değer\",\n    check: \"Kontrol\",\n    this_will_appear_as_is: \"*Bu, oluşturulan kodda olduğu gibi görünecektir.\",\n    comment: \"Yorum\",\n    add_field: \"Alan ekle\",\n    values: \"Değerler\",\n    size: \"Boyut\",\n    precision: \"Hassasiyet\",\n    set_precision: \"Hassasiyeti Ayarlar: (boyut, rakamlar)\",\n    use_for_batch_input: \"Toplu girdi için , kullanın\",\n    indices: \"İndeksler\",\n    add_index: \"İndeks ekle\",\n    select_fields: \"Alanları seç\",\n    title: \"Başlık\",\n    not_set: \"Ayarlanmadı\",\n    foreign: \"Yabancı\",\n    cardinality: \"Kardinalite\",\n    on_update: \"Güncelleme yap\",\n    on_delete: \"Silme yap\",\n    swap: \"Değiştir\",\n    one_to_one: \"Bire bir\",\n    one_to_many: \"Bire çok\",\n    many_to_one: \"Çoktan bire\",\n    content: \"İçerik\",\n    types_info:\n      \"Bu özellik PostgreSQL gibi nesne-ilişkisel DBMS'ler içindir.\\nMySQL veya MariaDB için kullanılırsa, ilgili json doğrulama kontrolüyle birlikte bir JSON türü oluşturulacaktır.\\nSQLite için kullanılırsa, bir BLOB'a çevrilecektir.\\nMSQL için kullanılırsa, ilk alana bir tür takma adı oluşturulacaktır.\",\n    table_deleted: \"Tablo silindi\",\n    area_deleted: \"Alan silindi\",\n    note_deleted: \"Not silindi\",\n    relationship_deleted: \"İlişki silindi\",\n    type_deleted: \"Tip silindi\",\n    cannot_connect: \"Bağlanamıyor, sütunların türleri farklı\",\n    copied_to_clipboard: \"Panoya kopyalandı\",\n    create_new_diagram: \"Yeni diagram oluştur\",\n    cancel: \"İptal\",\n    open_diagram: \"Diagramı aç\",\n    rename_diagram: \"Diagramı yeniden adlandır\",\n    export: \"Dışa aktar\",\n    export_image: \"Resim olarak dışa aktar\",\n    create: \"Oluştur\",\n    confirm: \"Onayla\",\n    last_modified: \"Son değişiklik\",\n    drag_and_drop_files:\n      \"Dosyayı buraya sürükleyip bırakın veya yüklemek için tıklayın.\",\n    upload_sql_to_generate_diagrams:\n      \"Tablolarınızı ve sütunlarınızı otomatik olarak oluşturmak için bir sql dosyası yükleyin.\",\n    overwrite_existing_diagram: \"Mevcut diyagramı üzerine yaz\",\n    only_mysql_supported:\n      \"*Şimdilik sadece MySQL veritabanları desteklenmektedir.\",\n    blank: \"Boş\",\n    filename: \"Dosya adı\",\n    table_w_no_name: \"Adı olmayan tablo belirlendi\",\n    duplicate_table_by_name: \"Tekrar eden tablo adı '{{tableName}}'\",\n    empty_field_name: \"'{{tableName}} tablosunda boş alan `name`\",\n    empty_field_type: \"'{{tableName}} tablosunda boş tip `type`\",\n    no_values_for_field:\n      \"'{{tableName}}' tablosunun '{{fieldName}}' alanı `{{type}}` türündedir ancak hiçbir değer belirtilmemiştir\",\n    default_doesnt_match_type:\n      \"{{tableName}} tablosundaki '{{fieldName}}' alanı için varsayılan değer türüyle eşleşmiyor\",\n    not_null_is_null:\n      \"'{{tableName}}' tablosunun '{{fieldName}}' alanı NULL DEĞİL ancak varsayılan olarak NULL\",\n    duplicate_fields:\n      \"Tablo '{{tableName}}' içinde '{{fieldName}}' adıyla yinelenen tablo alanları\",\n    duplicate_index:\n      \"'{{tableName}}' tablosunda '{{indexName}}' adına göre yinelenen dizin\",\n    empty_index:\n      \"'{{tableName}}' tablosundaki dizin hiçbir sütunu indexlemiyor\",\n    no_primary_key: \"'{{tableName}} tablosunun birincil anahtarı yok\",\n    type_with_no_name: \"Adı olmayan bir tür bildirilmiş\",\n    duplicate_types: \"'{{typeName}}' adına göre yinelenen türler\",\n    type_w_no_fields: \"Alanı olmayan boş bir '{{typeName}}' türü bildirilmiş\",\n    empty_type_field_name: \"Boş alan `name` in type '{{typeName}}'\",\n    empty_type_field_type: \"Boş alan `type` '{{typeName}}' türünde\",\n    no_values_for_type_field:\n      \"'{{typeName}}' türündeki '{{fieldName}}' alanı `{{type}}` türündedir ancak hiçbir değer belirtilmemiştir\",\n    duplicate_type_fields:\n      \"'{{typeName}}' türünde '{{fieldName}}' adına göre yinelenen tür alanları\",\n    duplicate_reference: \"'{{refName}}' adıyla yinelenen referans\",\n    circular_dependency: \"Tablo '{{refName}}' içeren döngüsel bağımlılık\",\n    timeline: \"Zaman çizelgesi\",\n    priority: \"Öncelik\",\n    none: \"Hiçbiri\",\n    low: \"Düşük\",\n    medium: \"Orta\",\n    high: \"Yüksek\",\n    sort_by: \"Sırala\",\n    my_order: \"Benim sıram\",\n    completed: \"Tamamlandı\",\n    alphabetically: \"Alfabetik\",\n    add_task: \"Görev ekle\",\n    details: \"Detaylar\",\n    no_tasks: \"Henüz bir görev yok\",\n    no_activity: \"Henüz bir etkinlik yok\",\n    move_element: \"{{name}} öğesini {{coords}} konumuna taşı\",\n    edit_area: \"{{extra}} Alanı düzenle {{areaName}}\",\n    delete_area: \"Alanı sil {{areaName}}\",\n    edit_note: \"{{extra}} Notu düzenle {{noteTitle}}\",\n    delete_note: \"Notu sil {{noteTitle}}\",\n    edit_table: \"{{extra}} Tabloyu düzenle {{tableName}}\",\n    delete_table: \"Tabloyu sil {{tableName}}\",\n    edit_type: \"{{extra}} Türü düzenle {{typeName}}\",\n    delete_type: \"Tip sil {{typeName}}\",\n    add_relationship: \"İlişki ekle\",\n    edit_relationship: \"{{extra}} İlişkiyi düzenle {{refName}}\",\n    delete_relationship: \"İlişkiyi sil {{refName}}\",\n    not_found: \"Bulunamadı\",\n    pick_db: \"Veritabanı seç\",\n    generic: \"Genel\",\n    generic_description:\n      \"Genel diyagramlar herhangi bir SQL türüne dışa aktarılabilir ancak az sayıda veri türünü destekler.\",\n    enums: \"Enums\",\n    add_enum: \"Enum ekle\",\n    edit_enum: \"{{extra}} Enum'u düzenle {{enumName}}\",\n    delete_enum: \"Enum'u sil\",\n    enum_w_no_name: \"İsimsiz bir enum bulundu\",\n    enum_w_no_values: \"Değerleri olmayan '{{enumName}}' adlı enum bulundu\",\n    duplicate_enums: \"'{{enumName}}' adında yinelenen enumlar var\",\n    no_enums: \"Enum yok\",\n    no_enums_text: \"Burada enum tanımlayın\",\n    declare_array: \"Dizi bildir\",\n    empty_index_name: \"'{{tableName}}' tablosunda isimsiz bir dizin bildirildi\",\n    didnt_find_diagram: \"Oops! Diyagram bulunamadı.\",\n  },\n};\n\nexport { tr, turkish };\n"
  },
  {
    "path": "src/i18n/locales/ug.js",
    "content": "const uyghur = {\n  name: \"Uyghur\",\n  native_name: \"ئۇيغۇرچە\",\n  code: \"ug\",\n};\n\nconst ug = {\n  translation: {\n    report_bug: \"بۇغ رېپورت قىلىڭ\",\n    import_from: \"ئېكىر\",\n    import: \"ئېكىر\",\n    file: \"ھۆججەت\",\n    new: \"يېڭى\",\n    new_window: \"يېڭى دەرۋازا\",\n    open: \"ئېچىش\",\n    save: \"ساقلاش\",\n    save_as: \"دەپ ساقلاش\",\n    save_as_template: \"شablon دەپ ساقلاش\",\n    template_saved: \"شablon ساقلانغان!\",\n    rename: \"ئادىنى ئۆزگەرتىش\",\n    delete_diagram: \"رەسمنى ئۆچۈرۈش\",\n    are_you_sure_delete_diagram:\n      \"سىز ھەقىقەتەن بۇ رەسمنى ئۆچۈرۈشنى خالايمسىز؟ بۇ ھەرىكەت قايتا قۇرغىلى بولمايدۇ.\",\n    oops_smth_went_wrong: \"ئوپ! بىر نەرسە خاتا بولدى.\",\n    import_diagram: \"رەسمنى ئېكىر\",\n    import_from_source: \"SQL دىن ئېكىر\",\n    export_as: \"دەپ ئېكسپورت قىلىش\",\n    export_source: \"SQL ئېكسپورت\",\n    models: \"مودېللار\",\n    exit: \"چىقىش\",\n    edit: \"تەھرىرلاش\",\n    undo: \"قايتۇرۇش\",\n    redo: \"يېڭىدىن قىلىش\",\n    clear: \"تازىلاش\",\n    are_you_sure_clear:\n      \"سىز ھەقىقەتەن بۇ رەسمنى تازىلاشنى خالايمسىز؟ بۇ قايتا قۇرغىلى بولمايدۇ.\",\n    cut: \"كېسىش\",\n    copy: \"نۇسخا ئېلىش\",\n    paste: \"قويۇش\",\n    duplicate: \"نۇسخىسىنى ياساش\",\n    delete: \"ئۆچۈرۈش\",\n    copy_as_image: \"رەسىم سۈپىتىدە نۇسخا ئېلىش\",\n    view: \"كۆرۈش\",\n    header: \"مېنۇ بار\",\n    sidebar: \"يانتۇ بار\",\n    issues: \"مەسىلىلەر\",\n    presentation_mode: \"تەqdimات رېژىمى\",\n    strict_mode: \"تىزىملىك رېژىمى\",\n    field_details: \"ئالاقە تەپسىلاتلىرى\",\n    reset_view: \"كۆرۈشنى قايتا قۇرۇش\",\n    show_grid: \"تارماقنى كۆرسىتىش\",\n    show_cardinality: \"كارتىنالىتىنى كۆرسىتىش\",\n    theme: \"تېما\",\n    light: \"يېنىق\",\n    dark: \"قارا\",\n    zoom_in: \"زوم قىلىش\",\n    zoom_out: \"زومنى تۆۋەنلىتىش\",\n    fullscreen: \"تولۇق ئېكران\",\n    settings: \"تەڭشەك\",\n    show_timeline: \"ۋاقىت جەدۋىلىنى كۆرسىتىش\",\n    autosave: \"ئۆز-ئۆزىگە ساقلاش\",\n    panning: \"پانننگ\",\n    table_width: \"جەدۋەل كەڭلىكى\",\n    language: \"تىل\",\n    flush_storage: \"ساقلاشنى تازىلاش\",\n    are_you_sure_flush_storage:\n      \"سىز ھەقىقەتەن ساقلاشنى تازىلاشنى خالايمسىز؟ بۇ سىزنىڭ بارلىق رەسملەرنى ۋە خاس شablونلارنى قايتا قۇرغىلى بولمايدۇ.\",\n    storage_flushed: \"ساقلاش تازىلاندى\",\n    help: \"ياردەم\",\n    shortcuts: \"قىسقا يوللار\",\n    ask_on_discord: \"بىز بىلەن Discord دا سوراڭ\",\n    feedback: \"پىكىر\",\n    no_changes: \"بىرەر ئۆزگىرىش يوق\",\n    loading: \"يۈكلەش...\",\n    last_saved: \"ئاخىرىدا ساقلانغان\",\n    saving: \"ساقلاۋاتىدۇ...\",\n    failed_to_save: \"ساقلاشقا مەغلۇپ بولدى\",\n    fit_window_reset: \"دەرۋازىنى ماسلاشتۇرۇش / قايتا قۇرۇش\",\n    zoom: \"زوم\",\n    add_table: \"جەدۋەل قوشۇش\",\n    add_area: \"ئارالۇق قوشۇش\",\n    add_note: \"بەلگە قوشۇش\",\n    add_type: \"تۈر قوشۇش\",\n    to_do: \"ئورۇنلىشىش\",\n    tables: \"جەدۋەللەر\",\n    relationships: \"مۇناسىۋەتلەر\",\n    subject_areas: \"مەزمۇن بۆلەكلىرى\",\n    notes: \"بەلگىلەر\",\n    types: \"تۈرلەر\",\n    search: \"ئىزدەش...\",\n    no_tables: \"جەدۋەل يوق\",\n    no_tables_text: \"رەسمنى ياساشنى باشلاڭ!\",\n    no_relationships: \"مۇناسىۋەت يوق\",\n    no_relationships_text: \"ئالاقە قۇرۇش ئۈچۈن بۆلەكلىرىنى تارتىڭ!\",\n    no_subject_areas: \"مەزمۇن بۆلەكلىرى يوق\",\n    no_subject_areas_text: \"جەدۋەللەرنى مەزمۇن بۆلەكلىرىگە قوشۇڭ!\",\n    no_notes: \"بەلگىلەر يوق\",\n    no_notes_text: \"قوشۇمچە ئۇچۇرنى خاتىرىلەش ئۈچۈن بەلگىلەرنى ئىشلىتىڭ\",\n    no_types: \"تۈرلەر يوق\",\n    no_types_text: \"خاس سانلىق مەلۇمات تۈرلىرىنى ياساڭ\",\n    no_issues: \"مەسىلىلەر تېپىلمىدى.\",\n    strict_mode_is_on_no_issues:\n      \"تىزىملىك رېژىمى قوزغىتىلغان، شۇڭا مەسىلىلەر كۆرۈلمەيدۇ.\",\n    name: \"ئاد\",\n    type: \"تۈر\",\n    null: \"Null\",\n    not_null: \"Null ئەمەس\",\n    primary: \"بىرلەشمىسى\",\n    unique: \"يەككە\",\n    autoincrement: \"ئۆز-ئۆزىگە قوشۇش\",\n    default_value: \"ئادەتتىكى قىممەت\",\n    check: \"تەكشۈرۈش ئىپادىسى\",\n    this_will_appear_as_is: \"*بۇ ياسالغان سكرىپتتە شۇنداقلا كۆرۈنىدۇ.\",\n    comment: \"ئىزاھات\",\n    add_field: \"بۆلەك قوشۇش\",\n    values: \"قىممەتلەر\",\n    size: \"ئۆلچەم\",\n    precision: \"دۇرۇسلىق\",\n    set_precision: \"دۇرۇسلىقىنى بەلگىلەش: (ئۆلچەم، رەقەم)\",\n    use_for_batch_input: \"بىر قېتىملىق كىرگۈزۈش ئۈچۈن ئىشلىتىش\",\n    indices: \"ئىنكس\",\n    add_index: \"ئىنكس قوشۇش\",\n    select_fields: \"بۆلەكلىرىنى تاللاش\",\n    title: \"باشلىق\",\n    not_set: \"بەلگىلەلمىگەن\",\n    foreign: \"تاشقى\",\n    cardinality: \"كارتىنالىتى\",\n    on_update: \"يېڭىلانغاندا\",\n    on_delete: \"ئۆچۈرۈلگەندە\",\n    swap: \"ئۆزگەرتىش\",\n    one_to_one: \"بىر-بىرگە\",\n    one_to_many: \"بىر-كۆپكە\",\n    many_to_one: \"كۆپ-بىرگە\",\n    content: \"مەزمۇن\",\n    types_info:\n      \"بۇ ئىقتىدار object-relational DBMS لىرىگە، PostgreSQL غا خاس.\\nئەگەر MySQL ياكى MariaDB غا ئىشلىتىلسە، مۇناسىۋەتلىك json توغرا تەكشۈرۈش بىلەن بىر JSON تۈرى ياسىلىدۇ.\\nئەگەر SQLite غا ئىشلىتىلسە، بۇ BLOB غا ئۆزگەرتىلىدۇ.\\nئەگەر MSSQL غا ئىشلىتىلسە، بىرىنچى بۆلەك ئۈچۈن بىر تۈر لەۋھەسى ياسىلىدۇ.\",\n    table_deleted: \"جەدۋەل ئۆچۈرۈلدى\",\n    area_deleted: \"ئارالۇق ئۆچۈرۈلدى\",\n    note_deleted: \"بەلگە ئۆچۈرۈلدى\",\n    relationship_deleted: \"مۇناسىۋەت ئۆچۈرۈلدى\",\n    type_deleted: \"تۈر ئۆچۈرۈلدى\",\n    cannot_connect: \"باغلىنىشقا بولمايدۇ، بۆلەك تۈرى پەرقلىق\",\n    copied_to_clipboard: \"كلىپبوردقا نۇسخا ئېلىندى\",\n    create_new_diagram: \"يېڭى رەسمنى ياساش\",\n    cancel: \"بەجىرىش\",\n    open_diagram: \"رەسمنى ئېچىش\",\n    rename_diagram: \"رەسمنىڭ نامىنى ئۆزگەرتىش\",\n    export: \"ئېكسپورت\",\n    export_image: \"رەسىمنى ئېكسپورت\",\n    create: \"ياساش\",\n    confirm: \"تاسدىقلاش\",\n    last_modified: \"ئاخىرىدا ئۆزگەرتىلگەن\",\n    drag_and_drop_files:\n      \"ھۆججەتلەرنى بۇ يەرگە تارتىپ قويۇڭ ياكى يۈكلەش ئۈچۈن بېسىڭ.\",\n    upload_sql_to_generate_diagrams:\n      \"جەدۋەل ۋە بۆلەكلىرىڭىزنى ئاپتوماتىك ياساش ئۈچۈن SQL ھۆججىتىنى يۈكلەڭ.\",\n    overwrite_existing_diagram: \"بار بولغان رەسمنى يېڭىدىن يازماق\",\n    only_mysql_supported: \"*ھازىرچە پەقەت MySQL سكرىپتلىرىنى يۈكلەش قوللايدۇ.\",\n    blank: \"بوش\",\n    filename: \"ھۆججەت نامى\",\n    table_w_no_name: \"ئادسىز جەدۋەل ئېلان قىلىندى\",\n    duplicate_table_by_name: \"ئاد بىلەن نۇسخا جەدۋەل '{{tableName}}'\",\n    empty_field_name: \"جەدۋەل '{{tableName}}' دا بوش بۆلەك نامى\",\n    empty_field_type: \"جەدۋەل '{{tableName}}' دا بوش بۆلەك تۈرى\",\n    no_values_for_field:\n      \"جەدۋەل '{{tableName}}' نىڭ بۆلەك '{{fieldName}}' نىڭ تۈرى {{type}}، ئەمما قىممەت بەلگىلەلمىدى\",\n    default_doesnt_match_type:\n      \"جەدۋەل '{{tableName}}' دا بۆلەك '{{fieldName}}' نىڭ ئادىتتىكى قىممىتى تۈرىگە ماس كەلمەيدۇ\",\n    not_null_is_null:\n      \"جەدۋەل '{{tableName}}' نىڭ بۆلەك '{{fieldName}}' نىڭ قىممىتى NOT NULL، ئەمما ئادىتتىكى NULL\",\n    duplicate_fields:\n      \"جەدۋەل '{{tableName}}' دا نام '{{fieldName}}' بولغان نۇسخا بۆلەك\",\n    duplicate_index:\n      \"جەدۋەل '{{tableName}}' دا نام '{{indexName}}' بولغان نۇسخا ئىنكس\",\n    empty_index: \"جەدۋەل '{{tableName}}' دا ئىنكس بۆلەك ئىنكس قىلمايدۇ\",\n    no_primary_key: \"جەدۋەل '{{tableName}}' دا بىرلەشمىسى يوق\",\n    type_with_no_name: \"نامسىز تۈر ئېلان قىلىندى\",\n    duplicate_types: \"نام '{{typeName}}' بولغان نۇسخا تۈرلەر\",\n    type_w_no_fields: \"بۆلەكلىرى يوق تۈر '{{typeName}}' ئېلان قىلىندى\",\n    empty_type_field_name: \"تۈر '{{typeName}}' دا بوش بۆلەك نامى\",\n    empty_type_field_type: \"تۈر '{{typeName}}' دا بوش بۆلەك تۈرى\",\n    no_values_for_type_field:\n      \"تۈر '{{typeName}}' نىڭ بۆلەك '{{fieldName}}' نىڭ تۈرى {{type}}، ئەمما قىممەت بەلگىلەلمىدى\",\n    duplicate_type_fields:\n      \"تۈر '{{typeName}}' دا نام '{{fieldName}}' بولغان نۇسخا تۈر بۆلەكلىرى\",\n    duplicate_reference: \"نام '{{refName}}' بولغان نۇسخا نىشان\",\n    circular_dependency: \"جەدۋەل '{{refName}}' دا دائىرىلىك باغلىقلىق\",\n    timeline: \"ۋاقىت جەدۋىلى\",\n    priority: \"ئالاھىدىلىك\",\n    none: \"يوق\",\n    low: \"تۆۋەن\",\n    medium: \"ئوتتۇرا\",\n    high: \"يۇقىرى\",\n    sort_by: \"بويىچە تىزىش\",\n    my_order: \"مەننىڭ تىزىم\",\n    completed: \"تاماملاندى\",\n    alphabetically: \"ئەپبە بويىچە\",\n    add_task: \"ۋەزىپە قوشۇش\",\n    details: \"تەپسىلاتلار\",\n    no_tasks: \"سىزنىڭ ھازىرچە ھېچقانداق ۋەزىپەڭىز يوق.\",\n    no_activity: \"سىزنىڭ ھازىرچە ھېچقانداق پائالىيىتىڭىز يوق.\",\n    move_element: \"{{name}} نى {{coords}} غا يۆتكىڭ\",\n    edit_area: \"{{extra}} ئارالۇقنى تەھرىرلىڭ {{areaName}}\",\n    delete_area: \"ئارالۇقنى ئۆچۈرۈڭ {{areaName}}\",\n    edit_note: \"{{extra}} بەلگىنى تەھرىرلىڭ {{noteTitle}}\",\n    delete_note: \"بەلگىنى ئۆچۈرۈڭ {{noteTitle}}\",\n    edit_table: \"{{extra}} جەدۋەلنى تەھرىرلىڭ {{tableName}}\",\n    delete_table: \"جەدۋەلنى ئۆچۈرۈڭ {{tableName}}\",\n    edit_type: \"{{extra}} تۈرنى تەھرىرلىڭ {{typeName}}\",\n    delete_type: \"تۈرنى ئۆچۈرۈڭ {{typeName}}\",\n    add_relationship: \"مۇناسىۋەت قوشۇڭ\",\n    edit_relationship: \"{{extra}} مۇناسىۋەتنى تەھرىرلىڭ {{refName}}\",\n    delete_relationship: \"مۇناسىۋەتنى ئۆچۈرۈڭ {{refName}}\",\n    not_found: \"تەپىلمايدۇ\",\n  },\n};\n\nexport { ug, uyghur };\n"
  },
  {
    "path": "src/i18n/locales/uk.js",
    "content": "const ukrainian = {\n  name: \"Ukrainian\",\n  native_name: \"Українська\",\n  code: \"uk\",\n};\n\nconst uk = {\n  translation: {\n    report_bug: \"Повідомити про помилку\",\n    import: \"Імпортувати\",\n    inherits: \"Успадковує\",\n    merging_column_w_inherited_definition:\n      \"Стовпець '{{fieldName}}' у таблиці '{{tableName}}' з успадкованим визначенням буде об'єднано\",\n    import_from: \"Імпортувати з\",\n    file: \"Файл\",\n    new: \"Новий\",\n    new_window: \"Нове вікно\",\n    no_saved_diagrams: \"У вас немає збережених діаграм\",\n    open: \"Відкрити\",\n    open_recent: \"Відкрити нещодавні\",\n    save: \"Зберегти\",\n    save_as: \"Зберегти як\",\n    save_as_template: \"Зберегти як шаблон\",\n    template_saved: \"Шаблон збережено!\",\n    rename: \"Перейменувати\",\n    delete_diagram: \"Видалити діаграму\",\n    are_you_sure_delete_diagram:\n      \"Ви впевнені, що хочете видалити цю діаграму? Це незворотно.\",\n    oops_smth_went_wrong: \"Упс! Щось пішло не так.\",\n    import_diagram: \"Імпортувати діаграму\",\n    import_from_source: \"Імпортувати з SQL\",\n    export_as: \"Експортувати як\",\n    export_source: \"Експортувати SQL\",\n    models: \"Моделі\",\n    exit: \"Вихід\",\n    edit: \"Редагувати\",\n    undo: \"Скасувати\",\n    redo: \"Повторити\",\n    clear: \"Очистити\",\n    are_you_sure_clear:\n      \"Ви впевнені, що хочете очистити діаграму? Це незворотно.\",\n    cut: \"Вирізати\",\n    copy: \"Копіювати\",\n    paste: \"Вставити\",\n    duplicate: \"Дублювати\",\n    delete: \"Видалити\",\n    copy_as_image: \"Скопіювати як зображення\",\n    view: \"Перегляд\",\n    header: \"Меню\",\n    sidebar: \"Бічна панель\",\n    issues: \"Проблеми\",\n    presentation_mode: \"Режим презентації\",\n    strict_mode: \"Строгий режим\",\n    field_details: \"Деталі поля\",\n    reset_view: \"Скинути перегляд\",\n    show_grid: \"Показати сітку\",\n    snap_to_grid: \"Прив’язати до сітки\",\n    show_datatype: \"Показати тип даних\",\n    show_cardinality: \"Показати кардинальність\",\n    theme: \"Тема\",\n    light: \"Світла\",\n    dark: \"Темна\",\n    zoom_in: \"Збільшити\",\n    zoom_out: \"Зменшити\",\n    fullscreen: \"Повний екран\",\n    settings: \"Налаштування\",\n    show_timeline: \"Показати хронологію\",\n    autosave: \"Автозбереження\",\n    panning: \"Прокрутка\",\n    show_debug_coordinates: \"Показати координати для налагодження\",\n    transform: \"Трансформація\",\n    viewbox: \"ViewBox\",\n    cursor_coordinates: \"Координати курсора\",\n    coordinate_space: \"Простір\",\n    coordinate_space_screen: \"Екран\",\n    coordinate_space_diagram: \"Діаграма\",\n    table_width: \"Ширина таблиці\",\n    language: \"Мова\",\n    flush_storage: \"Очистити сховище\",\n    are_you_sure_flush_storage:\n      \"Ви впевнені, що хочете очистити сховище? Це незворотно видалить всі ваші діаграми та шаблони.\",\n    storage_flushed: \"Сховище очищено\",\n    help: \"Допомога\",\n    shortcuts: \"Гарячі клавіші\",\n    ask_on_discord: \"Запитайте нас у Discord\",\n    feedback: \"Відгук\",\n    no_changes: \"Змін немає\",\n    loading: \"Завантаження...\",\n    last_saved: \"Останнє збереження\",\n    saving: \"Збереження...\",\n    failed_to_save: \"Не вдалося зберегти\",\n    fit_window_reset: \"Підлаштувати / Скинути\",\n    zoom: \"Масштаб\",\n    add_table: \"Додати таблицю\",\n    add_area: \"Додати область\",\n    add_note: \"Додати нотатку\",\n    add_type: \"Додати тип\",\n    to_do: \"Завдання\",\n    tables: \"Таблиці\",\n    relationships: \"Зв'язки\",\n    subject_areas: \"Тематичні області\",\n    notes: \"Нотатки\",\n    types: \"Типи\",\n    search: \"Пошук...\",\n    no_tables: \"Немає таблиць\",\n    no_tables_text: \"Почніть створювати вашу діаграму!\",\n    no_relationships: \"Немає зв’язків\",\n    no_relationships_text:\n      \"Перетягніть, щоб з’єднати поля та створити зв’язки!\",\n    no_subject_areas: \"Немає тематичних областей\",\n    no_subject_areas_text: \"Додайте тематичні області для групування таблиць!\",\n    no_notes: \"Немає нотаток\",\n    no_notes_text: \"Використовуйте нотатки для додаткової інформації\",\n    no_types: \"Немає типів\",\n    no_types_text: \"Створіть власні типи даних\",\n    no_issues: \"Проблем не виявлено.\",\n    strict_mode_is_on_no_issues:\n      \"Строгий режим вимкнено, тому проблеми не відображаються.\",\n    name: \"Назва\",\n    type: \"Тип\",\n    null: \"Null\",\n    not_null: \"Не Null\",\n    nullable: \"Можливе Null\",\n    primary: \"Первинний\",\n    unique: \"Унікальний\",\n    autoincrement: \"Автоінкремент\",\n    default_value: \"За замовчуванням\",\n    check: \"Перевірка виразу\",\n    this_will_appear_as_is:\n      \"*Це з’явиться у згенерованому скрипті без змін.\",\n    comment: \"Коментар\",\n    add_field: \"Додати поле\",\n    values: \"Значення\",\n    size: \"Розмір\",\n    precision: \"Точність\",\n    set_precision: \"Встановити точність: 'розмір, цифри'\",\n    use_for_batch_input: \"Використовуйте , для пакетного введення\",\n    indices: \"Індекси\",\n    add_index: \"Додати індекс\",\n    select_fields: \"Виберіть поля\",\n    title: \"Заголовок\",\n    not_set: \"Не встановлено\",\n    foreign: \"Зовнішній\",\n    cardinality: \"Кардинальність\",\n    on_update: \"При оновленні\",\n    on_delete: \"При видаленні\",\n    swap: \"Поміняти місцями\",\n    one_to_one: \"Один до одного\",\n    one_to_many: \"Один до багатьох\",\n    many_to_one: \"Багато до одного\",\n    content: \"Зміст\",\n    types_info:\n      \"Ця можливість призначена для об'єктно-реляційних СУБД, таких як PostgreSQL.\\nДля MySQL/MariaDB буде згенерований тип JSON з валідацією.\\nДля SQLite – буде перетворено у BLOB.\\nДля MSSQL – буде створено псевдонім типу на основі першого поля.\",\n    table_deleted: \"Таблицю видалено\",\n    area_deleted: \"Область видалено\",\n    note_deleted: \"Нотатку видалено\",\n    relationship_deleted: \"Зв’язок видалено\",\n    type_deleted: \"Тип видалено\",\n    cannot_connect: \"Неможливо з’єднати: стовпці мають різні типи\",\n    copied_to_clipboard: \"Скопійовано до буфера\",\n    create_new_diagram: \"Створити нову діаграму\",\n    cancel: \"Скасувати\",\n    open_diagram: \"Відкрити діаграму\",\n    rename_diagram: \"Перейменувати діаграму\",\n    export: \"Експортувати\",\n    export_image: \"Експортувати зображення\",\n    create: \"Створити\",\n    confirm: \"Підтвердити\",\n    last_modified: \"Остання зміна\",\n    drag_and_drop_files:\n      \"Перетягніть файл сюди або натисніть для завантаження.\",\n    upload_sql_to_generate_diagrams:\n      \"Завантажте SQL-файл для автоматичного створення таблиць.\",\n    overwrite_existing_diagram: \"Перезаписати існуючу діаграму\",\n    only_mysql_supported:\n      \"*Підтримується лише завантаження MySQL-скриптів.\",\n    blank: \"Порожній\",\n    filename: \"Назва файлу\",\n    table_w_no_name: \"Оголошено таблицю без назви\",\n    duplicate_table_by_name:\n      \"Дубльована таблиця з назвою '{{tableName}}'\",\n    empty_field_name: \"Порожнє поле `name` у таблиці '{{tableName}}'\",\n    empty_field_type: \"Порожнє поле `type` у таблиці '{{tableName}}'\",\n    no_values_for_field:\n      \"Поле '{{fieldName}}' у таблиці '{{tableName}}' має тип `{{type}}`, але значення не вказано\",\n    default_doesnt_match_type:\n      \"Значення за замовчуванням у полі '{{fieldName}}' таблиці '{{tableName}}' не відповідає типу\",\n    not_null_is_null:\n      \"Поле '{{fieldName}}' таблиці '{{tableName}}' — NOT NULL, але має NULL за замовчуванням\",\n    duplicate_fields:\n      \"Дубльовані поля '{{fieldName}}' у таблиці '{{tableName}}'\",\n    duplicate_index:\n      \"Дубльований індекс '{{indexName}}' у таблиці '{{tableName}}'\",\n    empty_index: \"Індекс у таблиці '{{tableName}}' не містить стовпців\",\n    no_primary_key: \"Таблиця '{{tableName}}' не має первинного ключа\",\n    type_with_no_name: \"Оголошено тип без назви\",\n    duplicate_types:\n      \"Дубльовані типи з назвою '{{typeName}}'\",\n    type_w_no_fields: \"Тип '{{typeName}}' оголошено без полів\",\n    empty_type_field_name:\n      \"Порожнє поле `name` у типі '{{typeName}}'\",\n    empty_type_field_type:\n      \"Порожнє поле `type` у типі '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Поле '{{fieldName}}' у типі '{{typeName}}' має тип `{{type}}`, але значення не вказано\",\n    duplicate_type_fields:\n      \"Дубльовані поля '{{fieldName}}' у типі '{{typeName}}'\",\n    duplicate_reference:\n      \"Дубльоване посилання з назвою '{{refName}}'\",\n    circular_dependency:\n      \"Циклічна залежність, що стосується '{{refName}}'\",\n    timeline: \"Хронологія\",\n    priority: \"Пріоритет\",\n    none: \"Немає\",\n    low: \"Низький\",\n    medium: \"Середній\",\n    high: \"Високий\",\n    sort_by: \"Сортувати за\",\n    my_order: \"Мій порядок\",\n    completed: \"Завершено\",\n    alphabetically: \"Алфавітно\",\n    add_task: \"Додати завдання\",\n    details: \"Деталі\",\n    no_tasks: \"У вас немає завдань\",\n    no_activity: \"У вас поки немає активності\",\n    move_element: \"Перемістити {{name}} до {{coords}}\",\n    edit_area: \"{{extra}} Редагувати область {{areaName}}\",\n    delete_area: \"Видалити область {{areaName}}\",\n    edit_note: \"{{extra}} Редагувати нотатку {{noteTitle}}\",\n    delete_note: \"Видалити нотатку {{noteTitle}}\",\n    edit_table: \"{{extra}} Редагувати таблицю {{tableName}}\",\n    delete_table: \"Видалити таблицю {{tableName}}\",\n    edit_type: \"{{extra}} Редагувати тип {{typeName}}\",\n    delete_type: \"Видалити тип {{typeName}}\",\n    add_relationship: \"Додати зв'язок\",\n    edit_relationship:\n      \"{{extra}} Редагувати зв'язок {{refName}}\",\n    delete_relationship: \"Видалити зв'язок {{refName}}\",\n    not_found: \"Не знайдено\",\n  },\n};\n\nexport { uk, ukrainian };\n"
  },
  {
    "path": "src/i18n/locales/ur.js",
    "content": "const urdu = {\n  name: \"Urdu\",\n  native_name: \"اردو\",\n  code: \"ur\",\n};\n\nconst ur = {\n  translation: {\n    report_bug: \"بگ رپورٹ کریں\",\n    import: \"درآمد کریں\",\n    inherits: \"وراثت\",\n    merging_column_w_inherited_definition:\n      \"ٹیبل '{{tableName}}' میں کالم '{{fieldName}}' کو وراثت میں ملی تعریف کے ساتھ ضم کیا جائے گا\",\n    import_from: \"یہاں سے درآمد کریں\",\n    file: \"فائل\",\n    new: \"نیا\",\n    new_window: \"نئی ونڈو\",\n    no_saved_diagrams: \"آپ کے پاس کوئی محفوظ شدہ ڈایاگرام نہیں ہے\",\n    open: \"کھولیں\",\n    open_recent: \"حالیہ کھولیں\",\n    save: \"محفوظ کریں\",\n    save_as: \"اس طرح محفوظ کریں\",\n    save_as_template: \"ٹیمپلیٹ کے طور پر محفوظ کریں\",\n    template_saved: \"ٹیمپلیٹ محفوظ ہو گیا!\",\n    rename: \"نام تبدیل کریں\",\n    delete_diagram: \"ڈایاگرام حذف کریں\",\n    are_you_sure_delete_diagram:\n      \"کیا آپ واقعی اس ڈایاگرام کو حذف کرنا چاہتے ہیں؟ یہ عمل ناقابل واپسی ہے۔\",\n    oops_smth_went_wrong: \"اوہ! کچھ غلط ہو گیا۔\",\n    import_diagram: \"ڈایاگرام درآمد کریں\",\n    import_from_source: \"SQL سے درآمد کریں\",\n    export_as: \"اس طرح برآمد کریں\",\n    export_source: \"SQL برآمد کریں\",\n    models: \"ماڈلز\",\n    exit: \"باہر نکلیں\",\n    edit: \"ترمیم کریں\",\n    undo: \"واپس کریں\",\n    redo: \"دوبارہ کریں\",\n    clear: \"صاف کریں\",\n    are_you_sure_clear:\n      \"کیا آپ واقعی ڈایاگرام کو صاف کرنا چاہتے ہیں؟ یہ عمل ناقابل واپسی ہے۔\",\n    cut: \"کٹ\",\n    copy: \"کاپی\",\n    paste: \"پیسٹ\",\n    duplicate: \"ڈپلیکیٹ\",\n    delete: \"حذف کریں\",\n    copy_as_image: \"تصویر کے طور پر کاپی کریں\",\n    view: \"دیکھیں\",\n    header: \"مینو بار\",\n    sidebar: \"سائیڈ بار\",\n    issues: \"مسائل\",\n    presentation_mode: \"پریزنٹیشن موڈ\",\n    strict_mode: \"سخت موڈ\",\n    field_details: \"فیلڈ کی تفصیلات\",\n    reset_view: \"منظر کو دوبارہ ترتیب دیں\",\n    show_grid: \"گرڈ دکھائیں\",\n    snap_to_grid: \"گرڈ سے چپکائیں\",\n    show_datatype: \"ڈیٹا کی قسم دکھائیں\",\n    show_cardinality: \"کارڈینلٹی دکھائیں\",\n    theme: \"تھیم\",\n    light: \"لائٹ\",\n    dark: \"ڈارک\",\n    zoom_in: \"زوم ان\",\n    zoom_out: \"زوم آؤٹ\",\n    fullscreen: \"فل سکرین\",\n    settings: \"ترتیبات\",\n    show_timeline: \"ٹائم لائن دکھائیں\",\n    autosave: \"آٹو سیو\",\n    panning: \"پیننگ\",\n    show_debug_coordinates: \"ڈیبگ کوآرڈینیٹس دکھائیں\",\n    transform: \"تبدیل کریں\",\n    viewbox: \"ویو باکس\",\n    cursor_coordinates: \"کرسر کوآرڈینیٹس\",\n    coordinate_space: \"اسپیس\",\n    coordinate_space_screen: \"سکرین\",\n    coordinate_space_diagram: \"ڈایاگرام\",\n    table_width: \"ٹیبل کی چوڑائی\",\n    language: \"زبان\",\n    flush_storage: \"اسٹوریج صاف کریں\",\n    are_you_sure_flush_storage:\n      \"کیا آپ واقعی اسٹوریج کو صاف کرنا چاہتے ہیں؟ یہ آپ کے تمام ڈایاگرام اور کسٹم ٹیمپلیٹس کو ناقابل واپسی طور پر حذف کر دے گا۔\",\n    storage_flushed: \"اسٹوریج صاف کر دیا گیا\",\n    help: \"مدد\",\n    shortcuts: \"شارٹ کٹس\",\n    ask_on_discord: \"Discord پر پوچھیں\",\n    feedback: \"فیڈبیک\",\n    no_changes: \"کوئی تبدیلی نہیں\",\n    loading: \"لوڈ ہو رہا ہے...\",\n    last_saved: \"آخری بار محفوظ کیا گیا\",\n    saving: \"محفوظ ہو رہا ہے...\",\n    failed_to_save: \"محفوظ کرنے میں ناکام\",\n    fit_window_reset: \"ونڈو میں فٹ کریں / ری سیٹ کریں\",\n    zoom: \"زوم\",\n    add_table: \"ٹیبل شامل کریں\",\n    add_area: \"علاقہ شامل کریں\",\n    add_note: \"نوٹ شامل کریں\",\n    add_type: \"قسم شامل کریں\",\n    to_do: \"کرنے کے کام\",\n    tables: \"ٹیبلز\",\n    relationships: \"تعلقات\",\n    subject_areas: \"موضوع کے علاقے\",\n    notes: \"نوٹس\",\n    types: \"اقسام\",\n    search: \"تلاش کریں...\",\n    no_tables: \"کوئی ٹیبل نہیں\",\n    no_tables_text: \"اپنا ڈایاگرام بنانا شروع کریں!\",\n    no_relationships: \"کوئی تعلقات نہیں\",\n    no_relationships_text: \"تعلقات بنانے کے لیے فیلڈز کو جوڑیں!\",\n    no_subject_areas: \"کوئی موضوع کے علاقے نہیں\",\n    no_subject_areas_text: \"ٹیبلز کو گروپ کرنے کے لیے موضوع کے علاقے شامل کریں!\",\n    no_notes: \"کوئی نوٹس نہیں\",\n    no_notes_text: \"اضافی معلومات ریکارڈ کرنے کے لیے نوٹس کا استعمال کریں\",\n    no_types: \"کوئی اقسام نہیں\",\n    no_types_text: \"اپنی کسٹم ڈیٹا کی اقسام بنائیں\",\n    no_issues: \"کوئی مسائل نہیں ملے\",\n    strict_mode_is_on_no_issues:\n      \"سخت موڈ بند ہے اس لیے کوئی مسائل نہیں دکھائے جائیں گے۔\",\n    name: \"نام\",\n    type: \"قسم\",\n    null: \"Null\",\n    not_null: \"Not null\",\n    nullable: \"Nullable\",\n    primary: \"Primary\",\n    unique: \"Unique\",\n    autoincrement: \"Autoincrement\",\n    default_value: \"ڈیفالٹ\",\n    check: \"چیک ایکسپریشن\",\n    this_will_appear_as_is: \"*یہ اسکرپٹ میں جیسا ہے ویسا ہی نظر آئے گا۔\",\n    comment: \"تبصرہ\",\n    add_field: \"فیلڈ شامل کریں\",\n    values: \"ویلیوز\",\n    size: \"سائز\",\n    precision: \"درستگی\",\n    set_precision: \"درستگی سیٹ کریں: 'سائز، ہندسے'\",\n    use_for_batch_input: \"بیچ ان پٹ کے لیے , استعمال کریں\",\n    indices: \"انڈیکسز\",\n    add_index: \"انڈیکس شامل کریں\",\n    select_fields: \"فیلڈز منتخب کریں\",\n    title: \"عنوان\",\n    not_set: \"سیٹ نہیں\",\n    foreign: \"Foreign\",\n    cardinality: \"کارڈینلٹی\",\n    on_update: \"اپ ڈیٹ پر\",\n    on_delete: \"حذف کرنے پر\",\n    swap: \"تبادلہ\",\n    one_to_one: \"One to one\",\n    one_to_many: \"One to many\",\n    many_to_one: \"Many to one\",\n    content: \"مواد\",\n    types_info:\n      \"یہ خصوصیت آبجیکٹ-ریلیشنل DBMSs جیسے PostgreSQL کے لیے ہے۔\\nاگر MySQL یا MariaDB کے لیے استعمال کیا جائے تو متعلقہ json توثیق چیک کے ساتھ ایک JSON قسم تیار کی جائے گی۔\\nاگر SQLite کے لیے استعمال کیا جائے تو یہ BLOB میں ترجمہ کیا جائے گا۔\\nاگر MSSQL کے لیے استعمال کیا جائے تو پہلے فیلڈ کے لیے ایک ٹائپ عرف تیار کیا جائے گا۔\",\n    table_deleted: \"ٹیبل حذف کر دیا گیا\",\n    area_deleted: \"علاقہ حذف کر دیا گیا\",\n    note_deleted: \"نوٹ حذف کر دیا گیا\",\n    relationship_deleted: \"تعلق حذف کر دیا گیا\",\n    type_deleted: \"قسم حذف کر دی گئی\",\n    cannot_connect: \"منسلک نہیں ہو سکتا، کالموں کی اقسام مختلف ہیں\",\n    copied_to_clipboard: \"کلپ بورڈ پر کاپی کر دیا گیا\",\n    create_new_diagram: \"نیا ڈایاگرام بنائیں\",\n    cancel: \"منسوخ کریں\",\n    open_diagram: \"ڈایاگرام کھولیں\",\n    rename_diagram: \"ڈایاگرام کا نام تبدیل کریں\",\n    export: \"برآمد کریں\",\n    export_image: \"تصویر برآمد کریں\",\n    create: \"تخلیق کریں\",\n    confirm: \"تصدیق کریں\",\n    last_modified: \"آخری ترمیم\",\n    drag_and_drop_files: \"فائل کو یہاں ڈریگ اور ڈراپ کریں یا اپ لوڈ کرنے کے لیے کلک کریں۔\",\n    upload_sql_to_generate_diagrams:\n      \"اپنے ٹیبلز اور کالمز کو خودکار طور پر تیار کرنے کے لیے ایک sql فائل اپ لوڈ کریں۔\",\n    overwrite_existing_diagram: \"موجودہ ڈایاگرام کو اوور رائٹ کریں\",\n    only_mysql_supported:\n      \"*فی الحال صرف MySQL اسکرپٹس لوڈ کرنے کی سہولت موجود ہے۔\",\n    blank: \"خالی\",\n    filename: \"فائل کا نام\",\n    table_w_no_name: \"بغیر نام کے ٹیبل کا اعلان کیا\",\n    duplicate_table_by_name: \"'{{tableName}}' نام سے ڈپلیکیٹ ٹیبل\",\n    empty_field_name: \"ٹیبل '{{tableName}}' میں خالی فیلڈ `name`\",\n    empty_field_type: \"ٹیبل '{{tableName}}' میں خالی فیلڈ `type`\",\n    no_values_for_field:\n      \"ٹیبل '{{tableName}}' کا فیلڈ '{{fieldName}}' `{{type}}` قسم کا ہے لیکن کوئی ویلیوز متعین نہیں کی گئی ہیں\",\n    default_doesnt_match_type:\n      \"ٹیبل '{{tableName}}' میں فیلڈ '{{fieldName}}' کی ڈیفالٹ ویلیو اس کی قسم سے مطابقت نہیں رکھتی\",\n    not_null_is_null:\n      \"ٹیبل '{{tableName}}' کا فیلڈ '{{fieldName}}' NOT NULL ہے لیکن اس کا ڈیفالٹ NULL ہے\",\n    duplicate_fields:\n      \"ٹیبل '{{tableName}}' میں '{{fieldName}}' نام سے ڈپلیکیٹ فیلڈز\",\n    duplicate_index:\n      \"ٹیبل '{{tableName}}' میں '{{indexName}}' نام سے ڈپلیکیٹ انڈیکس\",\n    empty_index: \"ٹیبل '{{tableName}}' میں انڈیکس کسی کالم کو انڈیکس نہیں کرتا\",\n    no_primary_key: \"ٹیبل '{{tableName}}' کی کوئی پرائمری کی نہیں ہے\",\n    type_with_no_name: \"بغیر نام کے قسم کا اعلان کیا\",\n    duplicate_types: \"'{{typeName}}' نام سے ڈپلیکیٹ اقسام\",\n    type_w_no_fields: \"بغیر فیلڈز کے خالی قسم '{{typeName}}' کا اعلان کیا\",\n    empty_type_field_name: \"قسم '{{typeName}}' میں خالی فیلڈ `name`\",\n    empty_type_field_type: \"قسم '{{typeName}}' میں خالی فیلڈ `type`\",\n    no_values_for_type_field:\n      \"قسم '{{typeName}}' کا فیلڈ '{{fieldName}}' `{{type}}` قسم کا ہے لیکن کوئی ویلیوز متعین نہیں کی گئی ہیں\",\n    duplicate_type_fields:\n      \"قسم '{{typeName}}' میں '{{fieldName}}' نام سے ڈپلیکیٹ ٹائپ فیلڈز\",\n    duplicate_reference: \"'{{refName}}' نام سے ڈپلیکیٹ حوالہ\",\n    circular_dependency: \"ٹیبل '{{refName}}' میں سرکلر انحصار\",\n    timeline: \"ٹائم لائن\",\n    priority: \"ترجیح\",\n    none: \"کوئی نہیں\",\n    low: \"کم\",\n    medium: \"درمیانہ\",\n    high: \"زیادہ\",\n    sort_by: \"ترتیب دیں\",\n    my_order: \"میری ترتیب\",\n    completed: \"مکمل\",\n    alphabetically: \"حروف تہجی کے لحاظ سے\",\n    add_task: \"ٹاسک شامل کریں\",\n    details: \"تفصیلات\",\n    no_tasks: \"آپ کے پاس ابھی تک کوئی ٹاسک نہیں ہے۔\",\n    no_activity: \"آپ کے پاس ابھی تک کوئی سرگرمی نہیں ہے۔\",\n    move_element: \"{{name}} کو {{coords}} پر منتقل کریں\",\n    edit_area: \"{{extra}} علاقہ {{areaName}} ترمیم کریں\",\n    delete_area: \"علاقہ {{areaName}} حذف کریں\",\n    edit_note: \"{{extra}} نوٹ {{noteTitle}} ترمیم کریں\",\n    delete_note: \"نوٹ {{noteTitle}} حذف کریں\",\n    edit_table: \"{{extra}} ٹیبل {{tableName}} ترمیم کریں\",\n    delete_table: \"ٹیبل {{tableName}} حذف کریں\",\n    edit_type: \"{{extra}} قسم {{typeName}} ترمیم کریں\",\n    delete_type: \"قسم {{typeName}} حذف کریں\",\n    add_relationship: \"تعلق شامل کریں\",\n    edit_relationship: \"{{extra}} تعلق {{refName}} ترمیم کریں\",\n    delete_relationship: \"تعلق {{refName}} حذف کریں\",\n    not_found: \"نہیں ملا\",\n    pick_db: \"ڈیٹا بیس منتخب کریں\",\n    generic: \"عام\",\n    generic_description:\n      \"عام ڈایاگرام کسی بھی SQL ذائقے میں برآمد کیے جا سکتے ہیں لیکن کچھ ڈیٹا کی اقسام کی حمایت کرتے ہیں۔\",\n    enums: \"Enums\",\n    add_enum: \"Enum شامل کریں\",\n    edit_enum: \"{{extra}} Enum {{enumName}} ترمیم کریں\",\n    delete_enum: \"Enum حذف کریں\",\n    enum_w_no_name: \"بغیر نام کے Enum ملا\",\n    enum_w_no_values: \"Enum '{{enumName}}' بغیر ویلیوز کے ملا\",\n    duplicate_enums: \"'{{enumName}}' نام سے ڈپلیکیٹ Enums\",\n    enum_deleted: \"Enum حذف کر دیا گیا\",\n    no_enums: \"کوئی Enums نہیں\",\n    no_enums_text: \"یہاں Enums کی وضاحت کریں\",\n    declare_array: \"Array کا اعلان کریں\",\n    empty_index_name: \"ٹیبل '{{tableName}}' میں بغیر نام کے انڈیکس کا اعلان کیا\",\n    didnt_find_diagram: \"اوہ! ڈایاگرام نہیں ملا۔\",\n    unsigned: \"Unsigned\",\n    share: \"شیئر کریں\",\n    unshare: \"شیئر ختم کریں\",\n    copy_link: \"لنک کاپی کریں\",\n    readme: \"README\",\n    failed_to_load: \"لوڈ کرنے میں ناکام۔ یقینی بنائیں کہ لنک درست ہے۔\",\n    share_info:\n      \"* اس لنک کو شیئر کرنے سے لائیو ریئل ٹائم تعاون کا سیشن نہیں بنے گا۔\",\n    show_relationship_labels: \"تعلقات کے لیبل دکھائیں\",\n    docs: \"دستاویزات\",\n    supported_types: \"معاون فائل کی اقسام:\",\n    bulk_update: \"بلک اپ ڈیٹ\",\n    multiselect: \"ملٹی سلیکٹ\",\n    export_saved_data: \"محفوظ شدہ ڈیٹا برآمد کریں\",\n    dbml_view: \"DBML منظر\",\n    tab_view: \"ٹیب منظر\",\n    label: \"لیبل\",\n    many_side_label: \"Many(n) سائیڈ لیبل\",\n    version: \"ورژن\",\n    versions: \"ورژنز\",\n    no_saved_versions: \"کوئی محفوظ شدہ ورژن نہیں\",\n    record_version: \"ورژن ریکارڈ کریں\",\n    commited_at: \"پر کمٹ کیا گیا\",\n    read_only: \"صرف پڑھنے کے لیے\",\n    continue: \"جاری رکھیں\",\n    restore_version: \"ورژن بحال کریں\",\n    restore_warning: \"دوسرا ورژن لوڈ کرنے سے کوئی بھی تبدیلیاں اوور رائٹ ہو جائیں گی۔\",\n    return_to_current: \"ڈایاگرام پر واپس جائیں\",\n    no_changes_to_record: \"ریکارڈ کرنے کے لیے کوئی تبدیلیاں نہیں\",\n    click_to_view: \"دیکھنے کے لیے کلک کریں\",\n    load_more: \"مزید لوڈ کریں\",\n    clear_cache: \"کیشے صاف کریں\",\n    cache_cleared: \"کیشے صاف کر دیا گیا\",\n    failed_to_record_version: \"ورژن ریکارڈ کرنے میں ناکام\",\n    failed_to_load_diagram: \"ڈایاگرام لوڈ کرنے میں ناکام\",\n    see_all: \"سب دیکھیں\",\n    insert_sql: \"SQL داخل کریں\",\n    upload_file: \"فائل اپ لوڈ کریں\",\n  },\n};\n\nexport { ur, urdu };\n"
  },
  {
    "path": "src/i18n/locales/vi.js",
    "content": "const vietnamese = {\n  name: \"Vietnamese\",\n  native_name: \"Tiếng Việt\",\n  code: \"vi\",\n};\n\nconst vi = {\n  translation: {\n    report_bug: \"Báo cáo lỗi\",\n    import_from: \"Nhập từ\",\n    import: \"Nhập\",\n    inherits: \"Kế thừa\",\n    merging_column_w_inherited_definition:\n      \"Cột '{{fieldName}}' trong bảng '{{tableName}}' với định nghĩa được kế thừa sẽ được gộp lại\",\n    file: \"Tệp\",\n    new: \"Tạo mới\",\n    new_window: \"Tạo mới cửa sổ\",\n    open: \"Mở\",\n    save: \"Lưu\",\n    save_as: \"Lưu thành\",\n    save_as_template: \"Lưu thành mẫu\",\n    template_saved: \"Mẫu đã được lưu!\",\n    rename: \"Đổi tên\",\n    delete_diagram: \"Xóa sơ đồ\",\n    are_you_sure_delete_diagram:\n      \"Bạn có chắc chắn muốn xóa sơ đồ này không? Hành động này không thể hoàn tác.\",\n    oops_smth_went_wrong: \"Ôi! Đã có lỗi xảy ra.\",\n    import_diagram: \"Nhập sơ đồ\",\n    import_from_source: \"Nhập từ SQL\",\n    export_as: \"Xuất thành\",\n    export_source: \"Xuất SQL\",\n    models: \"Mô hình\",\n    exit: \"Thoát\",\n    edit: \"Sửa\",\n    undo: \"Hoàn tác\",\n    redo: \"Làm lại\",\n    clear: \"Xóa\",\n    are_you_sure_clear:\n      \"Bạn có chắc chắn muốn xóa sơ đồ này không? Hành động này không thể hoàn tác.\",\n    cut: \"Cắt\",\n    copy: \"Sao chép\",\n    paste: \"Dán\",\n    duplicate: \"Nhân bản\",\n    delete: \"Xóa\",\n    copy_as_image: \"Sao chép dưới dạng hình ảnh\",\n    view: \"Xem\",\n    header: \"Thanh menu\",\n    sidebar: \"Thanh bên\",\n    issues: \"Vấn đề\",\n    presentation_mode: \"Chế độ trình bày\",\n    strict_mode: \"Chế độ nghiêm ngặt\",\n    field_details: \"Chi tiết trường\",\n    reset_view: \"Đặt lại chế độ xem\",\n    show_grid: \"Hiển thị lưới\",\n    snap_to_grid: \"Ghim vào lưới\",\n    show_datatype: \"Hiển thị kiểu dữ liệu\",\n    show_cardinality: \"Hiển thị số lượng\",\n    theme: \"Chủ đề\",\n    light: \"Sáng\",\n    dark: \"Tối\",\n    zoom_in: \"Phóng to\",\n    zoom_out: \"Thu nhỏ\",\n    fullscreen: \"Toàn màn hình\",\n    settings: \"Cài đặt\",\n    show_timeline: \"Hiển thị dòng thời gian\",\n    autosave: \"Tự động lưu\",\n    panning: \"Di chuyển\",\n    show_debug_coordinates: \"Hiển thị tọa độ debug\",\n    transform: \"Biến đổi\",\n    viewbox: \"View Box\",\n    cursor_coordinates: \"Tọa độ con trỏ\",\n    coordinate_space: \"Không gian\",\n    coordinate_space_screen: \"Màn hình\",\n    coordinate_space_diagram: \"Sơ đồ\",\n    table_width: \"Chiều rộng của bảng\",\n    language: \"Ngôn ngữ\",\n    flush_storage: \"Xóa bộ nhớ\",\n    are_you_sure_flush_storage:\n      \"Bạn có chắc chắn muốn xóa bộ nhớ không? Thao tác này sẽ xóa vĩnh viễn tất cả sơ đồ và mẫu tùy chỉnh của bạn.\",\n    storage_flushed: \"Bộ nhớ đã được xóa\",\n    help: \"Giúp đỡ\",\n    shortcuts: \"Phím tắt\",\n    ask_on_discord: \"Hỏi chúng tôi trên Discord\",\n    feedback: \"Nhận xét\",\n    no_changes: \"Không thay đổi\",\n    loading: \"Đang tải...\",\n    last_saved: \"Đã lưu lần cuối\",\n    saving: \"Đang lưu...\",\n    failed_to_save: \"Lưu thất bại\",\n    fit_window_reset: \"Đặt cửa sổ vừa độ rộng / Cài lại\",\n    zoom: \"Phóng to\",\n    add_table: \"Thêm bảng\",\n    add_area: \"Thêm vùng\",\n    add_note: \"Thêm ghi chú\",\n    add_type: \"Thêm kiểu\",\n    to_do: \"Việc cần làm\",\n    tables: \"Bảng\",\n    relationships: \"Quan hệ\",\n    subject_areas: \"Vùng\",\n    notes: \"Ghi chú\",\n    types: \"Kiểu\",\n    search: \"Tìm kiếm...\",\n    no_tables: \"Không có bảng\",\n    no_tables_text: \"Bắt đầu xây dựng sơ đồ của bạn!\",\n    no_relationships: \"Không có quan hệ\",\n    no_relationships_text: \"Kéo để kết nối các trường và tạo mối quan hệ\",\n    no_subject_areas: \"Không có vùng\",\n    no_subject_areas_text: \"Thêm vùng để nhóm các bảng!\",\n    no_notes: \"Không có ghi chú\",\n    no_notes_text: \"Sử dụng ghi chú để ghi lại thông tin bổ sung\",\n    no_types: \"Không có kiểu\",\n    no_types_text: \"Tạo kiểu dữ liệu tùy chỉnh của riêng bạn\",\n    no_issues: \"Không có vấn đề nào được phát hiện.\",\n    strict_mode_is_on_no_issues:\n      \"Chế độ nghiêm ngặt bị tắt nên sẽ không có vấn đề nào được hiển thị.\",\n    name: \"Tên\",\n    type: \"Kiểu\",\n    null: \"Không có giá trị\",\n    not_null: \"Có giá trị\",\n    nullable: \"Có thể không có giá trị\",\n    primary: \"Chính\",\n    unique: \"Duy nhất\",\n    autoincrement: \"Tự động tăng\",\n    default_value: \"Giá trị mặc định\",\n    check: \"Kiểm tra ràng buộc\",\n    this_will_appear_as_is: \"*Điều này sẽ xuất hiện trong đoạn lệnh được tạo như hiện tại\",\n    comment: \"Bình luận\",\n    add_field: \"Thêm trường\",\n    values: \"Giá trị\",\n    size: \"Kích cỡ\",\n    precision: \"Độ chính xác\",\n    set_precision: \"Đặt độ chính xác: (kích thước, chữ số)\",\n    use_for_batch_input: \"Sử dụng , cho đầu vào hàng loạt\",\n    indices: \"Chỉ mục\",\n    add_index: \"Thêm chỉ mục\",\n    select_fields: \"Chọn các trường\",\n    title: \"Tiêu đề\",\n    not_set: \"Chưa được thiết lập\",\n    foreign: \"Ngoại\",\n    cardinality: \"Quan hệ\",\n    on_update: \"Khi cập nhật\",\n    on_delete: \"Khi xóa\",\n    swap: \"Tráo đổi\",\n    one_to_one: \"Một - Một\",\n    one_to_many: \"Một - Nhiều\",\n    many_to_one: \"Nhiều - Một\",\n    content: \"Nội dung\",\n    types_info:\n      \"Tính năng này dành cho các hệ quản trị cơ sở dữ liệu quan hệ đối tượng như PostgreSQL.\\nNếu được sử dụng cho MySQL hoặc MariaDB, kiểu JSON sẽ được tạo bằng kiểm tra xác thực json tương ứng.\\nNếu được sử dụng cho SQLite, nó sẽ được dịch sang BLOB.\\nNếu được sử dụng cho MSSQL, một bí danh kiểu (type alias) cho trường đầu tiên sẽ được tạo ra.\",\n    table_deleted: \"Đã xóa bảng\",\n    area_deleted: \"Đã xóa vùng\",\n    note_deleted: \"Đã xóa ghi chú\",\n    relationship_deleted: \"Đã xóa quan hệ\",\n    type_deleted: \"Đã xóa kiểu\",\n    cannot_connect: \"Không thể kết nối, các cột có nhiều kiểu khác nhau\",\n    copied_to_clipboard: \"Sao chép vào bộ nhớ tạm\",\n    create_new_diagram: \"Tạo sơ đồ mới\",\n    cancel: \"Hủy bỏ\",\n    open_diagram: \"Mở sơ đồ\",\n    rename_diagram: \"Đổi tên sơ đồ\",\n    export: \"Xuất\",\n    export_image: \"Xuất hình ảnh\",\n    create: \"Tạo\",\n    confirm: \"Xác nhận\",\n    last_modified: \"Sửa đổi lần cuối\",\n    drag_and_drop_files: \"Kéo và thả tệp vào đây hoặc nhấp để tải lên.\",\n    upload_sql_to_generate_diagrams:\n      \"Tải tệp sql lên để tự động tạo bảng và cột của bạn.\",\n    overwrite_existing_diagram: \"Ghi đè sơ đồ hiện có\",\n    only_mysql_supported: \"*Hiện tại, chỉ hỗ trợ tải các tập lệnh MySQL.\",\n    blank: \"Trống\",\n    filename: \"Tên tập tin\",\n    table_w_no_name: \"Khai báo một bảng không có tên\",\n    duplicate_table_by_name: \"Bảng trùng lặp theo tên '{{tableName}}'\",\n    empty_field_name: \"Thiếu tên trường trong bảng '{{tableName}}'\",\n    empty_field_type: \"Thiếu kiểu dữ liệu của trường trong bảng '{{tableName}}'\",\n    no_values_for_field:\n      \"Trường '{{fieldName}}' của bảng '{{tableName}}' thuộc kiểu `{{type}}` nhưng không có giá trị nào được chỉ định\",\n    default_doesnt_match_type:\n      \"Giá trị mặc định cho trường '{{fieldName}}' trong bảng '{{tableName}}' không khớp với kiểu của nó\",\n    not_null_is_null:\n      \"Trường '{{fieldName}}' của bảng '{{tableName}}' là NOT NULL nhưng có giá trị mặc định là NULL\",\n    duplicate_fields:\n      \"Các trường trùng lặp theo tên '{{fieldName}}' trong bảng '{{tableName}}'\",\n    duplicate_index:\n      \"Chỉ mục trùng lặp theo tên '{{indexName}}' trong bảng '{{tableName}}'\",\n    empty_index: \"Chỉ mục trong bảng '{{tableName}}' không có cột nào\",\n    no_primary_key: \"Bảng '{{tableName}}' không có khóa chính\",\n    type_with_no_name: \"Khai báo một kiểu không có tên\",\n    duplicate_types: \"Các kiểu trùng lặp theo tên '{{typeName}}'\",\n    type_w_no_fields: \"Khai báo một kiểu rỗng '{{typeName}}' không có trường nào\",\n    empty_type_field_name: \"Thiếu tên trường trong kiểu '{{typeName}}'\",\n    empty_type_field_type: \"Thiếu kiểu dữ liệu của trường trong kiểu '{{typeName}}'\",\n    no_values_for_type_field:\n      \"Trường '{{fieldName}}' của kiểu '{{typeName}}' thuộc kiểu `{{type}}` nhưng không có giá trị nào được chỉ định\",\n    duplicate_type_fields:\n      \"Các trường trùng lặp theo tên '{{fieldName}}' trong kiểu '{{typeName}}'\",\n    duplicate_reference: \"Tham chiếu trùng lặp theo tên '{{refName}}'\",\n    circular_dependency: \"Phụ thuộc vòng tròn liên quan đến bảng '{{refName}}'\",\n    timeline: \"Dòng thời gian\",\n    priority: \"Độ ưu tiên\",\n    none: \"Không có\",\n    low: \"Thấp\",\n    medium: \"Trung bình\",\n    high: \"Cao\",\n    sort_by: \"Sắp xếp theo\",\n    my_order: \"Thứ tự của tôi\",\n    completed: \"Đã hoàn thành\",\n    alphabetically: \"Thứ tự bảng chữ cái\",\n    add_task: \"Thêm nhiệm vụ\",\n    details: \"Chi tiết\",\n    no_tasks: \"Bạn chưa có nhiệm vụ nào.\",\n    no_activity: \"Bạn chưa có hoạt động nào.\",\n    move_element: \"Di chuyển {{name}} tới {{coords}}\",\n    edit_area: \"{{extra}} Chỉnh sửa vùng {{areaName}}\",\n    delete_area: \"Xóa vùng {{areaName}}\",\n    edit_note: \"{{extra}} Chỉnh sửa ghi chú {{noteTitle}}\",\n    delete_note: \"Xóa ghi chú {{noteTitle}}\",\n    edit_table: \"{{extra}} Chỉnh sửa bảng {{tableName}}\",\n    delete_table: \"Xóa bảng {{tableName}}\",\n    edit_type: \"{{extra}} Chỉnh sửa kiểu {{typeName}}\",\n    delete_type: \"Xóa kiểu {{typeName}}\",\n    add_relationship: \"Thêm quan hệ\",\n    edit_relationship: \"{{extra}} Chỉnh sửa quan hệ {{refName}}\",\n    delete_relationship: \"Xóa quan hệ {{refName}}\",\n    not_found: \"Không tìm thấy\",\n    pick_db: \"Chọn cơ sở dữ liệu\",\n    generic: \"Chung\",\n    generic_description:\n      \"Các sơ đồ chung có thể được xuất sang bất kỳ kiểu SQL nào nhưng hỗ trợ ít kiểu dữ liệu.\",\n    enums: \"Enums\",\n    add_enum: \"Thêm enum\",\n    edit_enum: \"{{extra}} Chỉnh sửa enum {{enumName}}\",\n    delete_enum: \"Xóa enum\",\n    enum_w_no_name: \"Tìm thấy enum không có tên\",\n    enum_w_no_values: \"Tìm thấy enum '{{enumName}}' không có giá trị\",\n    duplicate_enums: \"Các enum trùng lặp với tên '{{enumName}}'\",\n    no_enums: \"Không có enum\",\n    no_enums_text: \"Định nghĩa enum ở đây\",\n    declare_array: \"Khai báo mảng\",\n    empty_index_name: \"Định nghĩa chỉ mục không có tên trong bảng '{{tableName}}'\",\n    didnt_find_diagram: \"Ôi! Không tìm thấy sơ đồ.\",\n    unsigned: \"Unsigned\",\n    share: \"Chia sẻ\",\n    unshare: \"Bỏ chia sẻ\",\n    copy_link: \"Sao chép liên kết\",\n    readme: \"README\",\n    failed_to_load: \"Không thể tải. Hãy chắc chắn rằng liên kết là chính xác.\",\n    share_info:\n      \"* Chia sẻ liên kết này sẽ không tạo ra một phiên hợp tác thời gian thực.\",\n    show_relationship_labels: \"Hiển thị nhãn quan hệ\",\n    docs: \"Tài liệu\",\n    supported_types: \"Các loại tệp được hỗ trợ:\",\n    bulk_update: \"Cập nhật hàng loạt\",\n    multiselect: \"Chọn nhiều\",\n    export_saved_data: \"Xuất dữ liệu đã lưu\",\n    dbml_view: \"Xem DBML\",\n    tab_view: \"Tab view\",\n    label: \"Nhãn\",\n    many_side_label: \"Many(n) side label\",\n    version: \"Phiên bản\",\n    versions: \"Các phiên bản\",\n    no_saved_versions: \"Không có phiên bản đã lưu\",\n    record_version: \"Ghi lại phiên bản\",\n    commited_at: \"Đã ghi lại lúc\",\n    read_only: \"Chỉ đọc\",\n    continue: \"Tiếp tục\",\n    restore_version: \"Khôi phục phiên bản\",\n    restore_warning: \"Tải phiên bản khác sẽ ghi đè lên bất kỳ thay đổi nào.\",\n    return_to_current: \"Quay lại sơ đồ\",\n    no_changes_to_record: \"Không có thay đổi nào để ghi lại\",\n    click_to_view: \"Nhấp để xem\",\n    load_more: \"Tải thêm\",\n    clear_cache: \"Xóa bộ nhớ cache\",\n    cache_cleared: \"Bộ nhớ cache đã được xóa\",\n    failed_to_record_version: \"Không thể ghi lại phiên bản\",\n    failed_to_load_diagram: \"Không thể tải sơ đồ\",\n  },\n};\n\nexport { vi, vietnamese };\n"
  },
  {
    "path": "src/i18n/locales/zh-tw.js",
    "content": "const traditionalChinese = {\n  name: \"Traditional Chinese\",\n  native_name: \"繁體中文\",\n  code: \"zh-TW\",\n};\n\nconst zh_tw = {\n  translation: {\n    report_bug: \"回報問題\",\n    import: \"匯入\",\n    inherits: \"繼承\",\n    merging_column_w_inherited_definition:\n      \"資料表「{{tableName}}」中的欄位「{{fieldName}}」帶有繼承定義，系統會合併。\",\n    import_from: \"匯入自\",\n    file: \"檔案\",\n    new: \"新增\",\n    new_window: \"開新視窗\",\n    no_saved_diagrams: \"尚未儲存任何圖表\",\n    open: \"開啟\",\n    open_recent: \"最近開啟\",\n    save: \"儲存\",\n    save_as: \"另存新檔\",\n    save_as_template: \"儲存為範本\",\n    template_saved: \"範本已儲存！\",\n    rename: \"重新命名\",\n    delete_diagram: \"刪除圖表\",\n    are_you_sure_delete_diagram:\n      \"確定要刪除此圖表嗎？此操作無法復原。\",\n    oops_smth_went_wrong: \"糟糕！發生錯誤。\",\n    import_diagram: \"匯入圖表\",\n    import_from_source: \"從 SQL 匯入\",\n    export_as: \"匯出為\",\n    export_source: \"匯出 SQL\",\n    models: \"模型\",\n    exit: \"結束\",\n    edit: \"編輯\",\n    undo: \"復原\",\n    redo: \"重做\",\n    clear: \"清除\",\n    are_you_sure_clear:\n      \"確定要清除圖表嗎？此操作無法復原。\",\n    cut: \"剪下\",\n    copy: \"複製\",\n    paste: \"貼上\",\n    duplicate: \"建立副本\",\n    delete: \"刪除\",\n    copy_as_image: \"複製為圖片\",\n    view: \"檢視\",\n    header: \"選單列\",\n    sidebar: \"側邊欄\",\n    issues: \"問題\",\n    presentation_mode: \"簡報模式\",\n    strict_mode: \"嚴謹模式\",\n    field_details: \"欄位詳細資料\",\n    reset_view: \"重設檢視\",\n    show_grid: \"顯示格線\",\n    snap_to_grid: \"貼齊格線\",\n    show_datatype: \"顯示資料型別\",\n    show_cardinality: \"顯示基數\",\n    theme: \"佈景主題\",\n    light: \"淺色\",\n    dark: \"深色\",\n    zoom_in: \"放大\",\n    zoom_out: \"縮小\",\n    fullscreen: \"全螢幕\",\n    settings: \"設定\",\n    show_timeline: \"顯示時間軸\",\n    autosave: \"自動儲存\",\n    panning: \"平移\",\n    show_debug_coordinates: \"顯示除錯座標\",\n    transform: \"轉換\",\n    viewbox: \"檢視框\",\n    cursor_coordinates: \"游標座標\",\n    coordinate_space: \"座標空間\",\n    coordinate_space_screen: \"螢幕座標\",\n    coordinate_space_diagram: \"圖表座標\",\n    table_width: \"資料表寬度\",\n    language: \"語言\",\n    flush_storage: \"清除儲存空間\",\n    are_you_sure_flush_storage:\n      \"確定要清除儲存空間嗎？這將會永久刪除所有圖表和自訂範本。\",\n    storage_flushed: \"儲存空間已清除\",\n    help: \"說明\",\n    shortcuts: \"快速鍵\",\n    ask_on_discord: \"到 Discord 提問\",\n    feedback: \"意見回饋\",\n    no_changes: \"無變更\",\n    loading: \"載入中...\",\n    last_saved: \"上次儲存時間\",\n    saving: \"儲存中...\",\n    failed_to_save: \"儲存失敗\",\n    fit_window_reset: \"符合視窗大小 / 重設\",\n    zoom: \"縮放\",\n    add_table: \"新增資料表\",\n    add_area: \"新增區域\",\n    add_note: \"新增註解\",\n    add_type: \"新增型別\",\n    to_do: \"待辦事項\",\n    tables: \"資料表\",\n    relationships: \"關聯\",\n    subject_areas: \"主題區域\",\n    notes: \"註解\",\n    types: \"型別\",\n    search: \"搜尋...\",\n    no_tables: \"尚無資料表\",\n    no_tables_text: \"開始建立圖表！\",\n    no_relationships: \"尚無關聯\",\n    no_relationships_text: \"拖曳以連接欄位並建立關聯！\",\n    no_subject_areas: \"尚無主題區域\",\n    no_subject_areas_text: \"將主題區域新增至群組資料表！\",\n    no_notes: \"尚無註解\",\n    no_notes_text: \"使用註解紀錄額外資訊\",\n    no_types: \"尚無型別\",\n    no_types_text: \"建立自訂資料型別\",\n    no_issues: \"未偵測到問題。\",\n    strict_mode_is_on_no_issues:\n      \"嚴謹模式已關閉，因此不會顯示任何問題。\",\n    name: \"名稱\",\n    type: \"型別\",\n    null: \"允許空值\",\n    not_null: \"不允許空值\",\n    nullable: \"可為空值\",\n    primary: \"主鍵\",\n    unique: \"唯一值\",\n    autoincrement: \"自動遞增\",\n    default_value: \"預設值\",\n    check: \"檢查條件\",\n    this_will_appear_as_is: \"*這將以原樣出現在產出的指令碼中。\",\n    comment: \"註解\",\n    add_field: \"新增欄位\",\n    values: \"值\",\n    size: \"大小\",\n    precision: \"精確度\",\n    set_precision: \"設定精確度：'大小, 位數'\",\n    use_for_batch_input: \"使用逗號(,)進行批次輸入\",\n    indices: \"索引\",\n    add_index: \"新增索引\",\n    select_fields: \"選擇欄位\",\n    title: \"標題\",\n    not_set: \"未設定\",\n    foreign: \"外鍵\",\n    cardinality: \"基數\",\n    on_update: \"更新時\",\n    on_delete: \"刪除時\",\n    swap: \"交換\",\n    one_to_one: \"一對一\",\n    one_to_many: \"一對多\",\n    many_to_one: \"多對一\",\n    content: \"內容\",\n    types_info:\n      \"此功能適用於 PostgreSQL 等物件關聯式 DBMS。\\n若用於 MySQL 或 MariaDB，將產出具 JSON 驗證檢查的 JSON 型別。\\n若用於 SQLite，將轉換為 BLOB。\\n若用於 MSSQL，將產出指向第一個欄位的型別別名。\",\n    table_deleted: \"資料表已刪除\",\n    area_deleted: \"區域已刪除\",\n    note_deleted: \"註解已刪除\",\n    relationship_deleted: \"關聯已刪除\",\n    type_deleted: \"型別已刪除\",\n    cannot_connect: \"無法連線，欄位型別不符\",\n    copied_to_clipboard: \"已複製到剪貼簿\",\n    create_new_diagram: \"建立新圖表\",\n    cancel: \"取消\",\n    open_diagram: \"開啟圖表\",\n    rename_diagram: \"重新命名圖表\",\n    export: \"匯出\",\n    export_image: \"匯出圖片\",\n    create: \"建立\",\n    confirm: \"確認\",\n    last_modified: \"最後修改\",\n    drag_and_drop_files: \"將檔案拖曳至此處或點選以上傳。\",\n    upload_sql_to_generate_diagrams:\n      \"上傳 SQL 檔案以自動產出資料表及欄位。\",\n    overwrite_existing_diagram: \"覆蓋現有圖表\",\n    only_mysql_supported:\n      \"*目前僅支援載入 MySQL 指令碼。\",\n    blank: \"空白\",\n    filename: \"檔案名稱\",\n    table_w_no_name: \"有未命名的資料表\",\n    duplicate_table_by_name: \"資料表名稱「{{tableName}}」重複\",\n    empty_field_name: \"資料表「{{tableName}}」中有未命名的欄位\",\n    empty_field_type: \"資料表「{{tableName}}」中有未指定型別的欄位\",\n    no_values_for_field:\n      \"資料表「{{tableName}}」中的欄位「{{fieldName}}」型別為「{{type}}」但未指定任何值\",\n    default_doesnt_match_type:\n      \"資料表「{{tableName}}」中欄位「{{fieldName}}」的預設值與其型別不符\",\n    not_null_is_null:\n      \"資料表「{{tableName}}」中的欄位「{{fieldName}}」設定為不可為空值但預設為空值\",\n    duplicate_fields:\n      \"資料表「{{tableName}}」中欄位名稱「{{fieldName}}」重複\",\n    duplicate_index:\n      \"資料表「{{tableName}}」中索引名稱「{{indexName}}」重複\",\n    empty_index: \"資料表「{{tableName}}」中有未包含任何欄位的索引\",\n    no_primary_key: \"資料表「{{tableName}}」未設定主鍵\",\n    type_with_no_name: \"有未命名的型別\",\n    duplicate_types: \"型別名稱「{{typeName}}」重複\",\n    type_w_no_fields: \"型別「{{typeName}}」未定義任何欄位\",\n    empty_type_field_name: \"型別「{{typeName}}」中有未命名的欄位\",\n    empty_type_field_type: \"型別「{{typeName}}」中有未指定型別的欄位\",\n    no_values_for_type_field:\n      \"型別「{{typeName}}」中的欄位「{{fieldName}}」型別為「{{type}}」但未指定任何值\",\n    duplicate_type_fields:\n      \"型別「{{typeName}}」中欄位名稱「{{fieldName}}」重複\",\n    duplicate_reference: \"關聯名稱「{{refName}}」重複\",\n    circular_dependency: \"資料表「{{refName}}」存在循環相依性問題\",\n    timeline: \"時間軸\",\n    priority: \"優先順序\",\n    none: \"無\",\n    low: \"低\",\n    medium: \"中\",\n    high: \"高\",\n    sort_by: \"排序方式\",\n    my_order: \"自訂排序\",\n    completed: \"已完成\",\n    alphabetically: \"依字母順序\",\n    add_task: \"新增工作項目\",\n    details: \"詳細資料\",\n    no_tasks: \"目前尚無工作項目。\",\n    no_activity: \"目前尚無任何活動紀錄。\",\n    move_element: \"將「{{name}}」移動至 {{coords}}\",\n    edit_area: \"{{extra}} 編輯區域「{{areaName}}」\",\n    delete_area: \"刪除區域「{{areaName}}」\",\n    edit_note: \"{{extra}} 編輯註解「{{noteTitle}}」\",\n    delete_note: \"刪除註解「{{noteTitle}}」\",\n    edit_table: \"{{extra}} 編輯資料表「{{tableName}}」\",\n    delete_table: \"刪除資料表「{{tableName}}」\",\n    edit_type: \"{{extra}} 編輯型別「{{typeName}}」\",\n    delete_type: \"刪除型別「{{typeName}}」\",\n    add_relationship: \"新增關聯\",\n    edit_relationship: \"{{extra}} 編輯關聯「{{refName}}」\",\n    delete_relationship: \"刪除關聯「{{refName}}」\",\n    not_found: \"找不到\",\n    pick_db: \"選擇資料庫\",\n    generic: \"通用\",\n    generic_description:\n      \"通用圖表可匯出至任何 SQL 格式，但僅支援少數資料型別。\",\n    enums: \"列舉\",\n    add_enum: \"新增列舉\",\n    edit_enum: \"{{extra}} 編輯列舉「{{enumName}}」\",\n    delete_enum: \"刪除列舉\",\n    enum_w_no_name: \"未指定名稱的列舉\",\n    enum_w_no_values: \"列舉「{{enumName}}」未定義任何值\",\n    duplicate_enums: \"列舉名稱「{{enumName}}」重複\",\n    no_enums: \"尚無列舉\",\n    no_enums_text: \"在此定義列舉\",\n    declare_array: \"宣告陣列\",\n    empty_index_name: \"資料表「{{tableName}}」中有未命名的索引\",\n    didnt_find_diagram: \"糟糕！找不到該圖表。\",\n    unsigned: \"無號數\",\n    share: \"分享\",\n    unshare: \"取消分享\",\n    copy_link: \"複製連結\",\n    readme: \"README\",\n    failed_to_load: \"載入失敗。請確認連結是否正確。\",\n    share_info:\n      \"* 分享此連結不會建立即時的協作工作階段。\",\n    show_relationship_labels: \"顯示關聯標籤\",\n    docs: \"文件\",\n    supported_types: \"支援的檔案類型：\",\n    bulk_update: \"批次更新\",\n    multiselect: \"多重選取\",\n    export_saved_data: \"匯出儲存的資料\",\n    dbml_view: \"DBML 檢視\",\n    tab_view: \"分頁檢視\",\n    label: \"標籤\",\n    many_side_label: \"多數側(n)標籤\",\n    version: \"版本\",\n    versions: \"版本\",\n    no_saved_versions: \"尚未儲存任何版本\",\n    record_version: \"紀錄版本\",\n    commited_at: \"提交時間\",\n    read_only: \"唯讀\",\n    continue: \"繼續\",\n    restore_version: \"還原版本\",\n    restore_warning: \"載入其他版本會覆寫所有變更。\",\n    return_to_current: \"返回圖表\",\n    no_changes_to_record: \"沒有可紀錄的變更\",\n    click_to_view: \"點選以檢視\",\n    load_more: \"載入更多\",\n    clear_cache: \"清除快取\",\n    cache_cleared: \"快取已清除\",\n    failed_to_record_version: \"紀錄版本失敗\",\n    failed_to_load_diagram: \"載入圖表失敗\",\n    see_all: \"檢視全部\",\n  },\n};\n\nexport { zh_tw, traditionalChinese };\n"
  },
  {
    "path": "src/i18n/locales/zh.js",
    "content": "const chinese = {\n  name: \"Simplified Chinese\",\n  native_name: \"简体中文\",\n  code: \"zh\",\n};\n\nconst zh = {\n  translation: {\n    report_bug: \"报告问题\",\n    import_from: \"导入\",\n    import: \"导入\",\n    file: \"文件\",\n    new: \"新建\",\n    new_window: \"在新标签中打开\",\n    open: \"打开\",\n    open_recent: \"打开最近的图表\",\n    save: \"保存\",\n    save_as: \"另存为\",\n    save_as_template: \"保存为模板\",\n    template_saved: \"模板已保存！\",\n    rename: \"重命名\",\n    delete_diagram: \"删除图表\",\n    are_you_sure_delete_diagram: \"确定要删除此图表吗？此操作不可逆转。\",\n    oops_smth_went_wrong: \"糟糕！出了些问题。\",\n    import_diagram: \"导入图表\",\n    import_from_source: \"导入 SQL 源代码\",\n    export_as: \"导出为\",\n    export_source: \"导出为 SQL 源代码\",\n    models: \"模型\",\n    exit: \"退出\",\n    edit: \"编辑\",\n    undo: \"撤销\",\n    redo: \"恢复\",\n    clear: \"清除\",\n    are_you_sure_clear: \"确定要清除图表吗？此操作不可逆转。\",\n    cut: \"剪切\",\n    copy: \"复制\",\n    paste: \"粘贴\",\n    duplicate: \"克隆\",\n    delete: \"删除\",\n    copy_as_image: \"复制画布为图片\",\n    view: \"视图\",\n    header: \"菜单栏\",\n    sidebar: \"侧边栏\",\n    issues: \"问题\",\n    presentation_mode: \"演示模式\",\n    strict_mode: \"严格模式\",\n    field_details: \"字段详情\",\n    reset_view: \"重置视图\",\n    show_datatype: \"显示数据类型\",\n    show_grid: \"显示网格\",\n    show_cardinality: \"显示关系\",\n    theme: \"主题\",\n    light: \"浅色\",\n    dark: \"深色\",\n    zoom_in: \"放大\",\n    zoom_out: \"缩小\",\n    fullscreen: \"全屏\",\n    settings: \"设置\",\n    show_timeline: \"修改记录\",\n    autosave: \"自动保存\",\n    panning: \"画布可拖动\",\n    show_relationship_labels: \"显示关系标签\",\n    show_debug_coordinates: \"显示调试坐标\",\n    transform: \"变换\",\n    viewbox: \"视图框\",\n    cursor_coordinates: \"光标坐标\",\n    coordinate_space: \"坐标空间\",\n    coordinate_space_screen: \"屏幕\",\n    coordinate_space_diagram: \"图表\",\n    table_width: \"表格宽度\",\n    language: \"语言\",\n    export_saved_data: \"导出保存的数据\",\n    flush_storage: \"清除存储\",\n    are_you_sure_flush_storage:\n      \"您确定要清除存储吗？此操作将无法恢复地删除您所有的图表和自定义模板。\",\n    storage_flushed: \"存储已清空\",\n    help: \"帮助\",\n    docs: \"文档\",\n    shortcuts: \"快捷键\",\n    ask_on_discord: \"在 Discord 联系我们\",\n    feedback: \"反馈\",\n    no_changes: \"没有更改\",\n    loading: \"加载中...\",\n    last_saved: \"上次保存\",\n    saving: \"保存中...\",\n    failed_to_save: \"保存失败\",\n    fit_window_reset: \"适应窗口/重置\",\n    zoom: \"缩放\",\n    add_table: \"添加表\",\n    add_area: \"添加区域\",\n    add_note: \"添加注释\",\n    add_type: \"添加类型\",\n    to_do: \"待办事项\",\n    tables: \"表\",\n    relationships: \"关系\",\n    subject_areas: \"主题区域\",\n    notes: \"注释\",\n    types: \"类型\",\n    search: \"搜索...\",\n    no_tables: \"空空如也\",\n    no_tables_text: \"开始构建您的图表！\",\n    no_relationships: \"空空如也\",\n    no_relationships_text: \"拖动以连接字段并形成关系！\",\n    no_subject_areas: \"空空如也\",\n    no_subject_areas_text: \"添加主题区域以分组表！\",\n    no_notes: \"空空如也\",\n    no_notes_text: \"使用注释记录额外信息\",\n    no_types: \"空空如也\",\n    no_types_text: \"制作您自己的自定义数据类型\",\n    no_issues: \"未检测到问题。\",\n    strict_mode_is_on_no_issues: \"严格模式已关闭，因此不会显示任何问题。\",\n    name: \"名称\",\n    type: \"类型\",\n    null: \"空\",\n    not_null: \"非空\",\n    primary: \"主键\",\n    unique: \"唯一\",\n    autoincrement: \"自增\",\n    default_value: \"默认值\",\n    check: \"检查表达式\",\n    this_will_appear_as_is: \"*此内容将按原样显示在生成的脚本中。\",\n    comment: \"注释\",\n    add_field: \"添加字段\",\n    values: \"值\",\n    size: \"大小\",\n    precision: \"精度\",\n    set_precision: \"设置精度：(大小，位数)\",\n    use_for_batch_input: \"用于批量输入，使用逗号\",\n    indices: \"索引\",\n    add_index: \"添加索引\",\n    select_fields: \"选择字段\",\n    title: \"标题\",\n    not_set: \"未设置\",\n    foreign: \"外键\",\n    cardinality: \"关系映射\",\n    on_update: \"更新时\",\n    on_delete: \"删除时\",\n    swap: \"交换\",\n    one_to_one: \"一对一\",\n    one_to_many: \"一对多\",\n    many_to_one: \"多对一\",\n    content: \"内容\",\n    types_info:\n      \"此功能适用于像 PostgreSQL 这样的对象关系型数据库管理系统。\\n如果用于 MySQL 或 MariaDB，将生成具有相应 JSON 验证检查的 JSON 类型。\\n如果用于 SQLite，它将被转换为 BLOB。\\n如果用于 MSSQL，将生成到第一个字段的类型别名。\",\n    table_deleted: \"表已删除\",\n    area_deleted: \"区域已删除\",\n    note_deleted: \"注释已删除\",\n    relationship_deleted: \"关系已删除\",\n    type_deleted: \"类型已删除\",\n    cannot_connect: \"无法连接，列具有不同的类型\",\n    copied_to_clipboard: \"已复制到剪贴板\",\n    create_new_diagram: \"创建新图表\",\n    cancel: \"取消\",\n    open_diagram: \"打开图表\",\n    rename_diagram: \"重命名图表\",\n    export: \"导出\",\n    export_image: \"导出图像\",\n    create: \"创建\",\n    confirm: \"确认\",\n    last_modified: \"最后修改\",\n    drag_and_drop_files: \"拖放文件到此处或点击上传。\",\n    upload_sql_to_generate_diagrams: \"上传 SQL 文件以自动生成表和列。\",\n    overwrite_existing_diagram: \"覆盖现有图表\",\n    only_mysql_supported: \"目前仅支持加载 MySQL 脚本。\",\n    blank: \"空\",\n    filename: \"文件名\",\n    table_w_no_name: \"声明了一个没有名称的表\",\n    duplicate_table_by_name: \"重复声明了名为 '{{tableName}}' 的表\",\n    empty_field_name: \"表 '{{tableName}}' 中的字段 `name` 为空\",\n    empty_field_type: \"表 '{{tableName}}' 中的字段 `type` 为空\",\n    no_values_for_field:\n      \"表 '{{tableName}}' 的 '{{fieldName}}' 字段类型为 `{{type}}`，但未指定任何值\",\n    default_doesnt_match_type:\n      \"表 '{{tableName}}' 中字段 '{{fieldName}}' 的默认值与其类型不匹配\",\n    not_null_is_null:\n      \"表 '{{tableName}}' 中的 '{{fieldName}}' 字段为 NOT NULL，但默认值为 NULL\",\n    duplicate_fields:\n      \"在表 '{{tableName}}' 中重复声明了名为 '{{fieldName}}' 的字段\",\n    duplicate_index:\n      \"在表 '{{tableName}}' 中重复声明了名为 '{{indexName}}' 的索引\",\n    empty_index: \"在表 '{{tableName}}' 中的索引未指定任何列\",\n    no_primary_key: \"表 '{{tableName}}' 没有主键\",\n    type_with_no_name: \"声明了一个没有名称的类型\",\n    duplicate_types: \"重复声明了名为 '{{typeName}}' 的类型\",\n    type_w_no_fields: \"声明了一个没有字段的空类型 '{{typeName}}'\",\n    empty_type_field_name: \"类型 '{{typeName}}' 中的字段 `name` 为空\",\n    empty_type_field_type: \"类型 '{{typeName}}' 中的字段 `type` 为空\",\n    no_values_for_type_field:\n      \"类型 '{{typeName}}' 的 '{{fieldName}}' 字段类型为 `{{type}}`，但未指定任何值\",\n    duplicate_type_fields:\n      \"在自定义类 '{{typeName}}' 中重复声明了名为 '{{fieldName}}' 的字段\",\n    duplicate_reference: \"重复声明了名为 '{{refName}}' 的引用\",\n    circular_dependency: \"涉及到表 '{{refName}}' 的循环依赖\",\n    timeline: \"时间轴\",\n    priority: \"优先级\",\n    none: \"无\",\n    low: \"低\",\n    medium: \"中\",\n    high: \"高\",\n    sort_by: \"排序方式\",\n    my_order: \"我的排序\",\n    completed: \"已完成\",\n    alphabetically: \"按字母顺序\",\n    add_task: \"添加任务\",\n    details: \"详情\",\n    no_tasks: \"您还没有任务。\",\n    no_activity: \"您还没有活动。\",\n    move_element: \"将 {{name}} 移动到 {{coords}}\",\n    edit_area: \"{{extra}} 编辑区域 {{areaName}}\",\n    delete_area: \"删除区域 {{areaName}}\",\n    edit_note: \"{{extra}} 编辑注释 {{noteTitle}}\",\n    delete_note: \"删除注释 {{noteTitle}}\",\n    edit_table: \"{{extra}} 编辑表格 {{tableName}}\",\n    delete_table: \"删除表格 {{tableName}}\",\n    edit_type: \"{{extra}} 编辑类型 {{typeName}}\",\n    delete_type: \"删除类型 {{typeName}}\",\n    add_relationship: \"添加关系\",\n    edit_relationship: \"{{extra}} 编辑关系 {{refName}}\",\n    delete_relationship: \"删除关系 {{refName}}\",\n    not_found: \"未找到\",\n    pick_db: \"选择数据库\",\n    generic: \"通用\",\n    generic_description:\n      \"通用图表可以导出为任何 SQL 格式，但仅支持有限的数据类型。\",\n    enums: \"枚举\",\n    add_enum: \"添加枚举\",\n    edit_enum: \"{{extra}} 编辑枚举 {{enumName}}\",\n    delete_enum: \"删除枚举\",\n    enum_w_no_name: \"声明了一个没有名称的枚举\",\n    enum_w_no_values: \"声明了一个没有值的枚举 '{{enumName}}'\",\n    duplicate_enums: \"重复声明了名为 '{{enumName}}' 的枚举\",\n    no_enums: \"没有枚举\",\n    no_enums_text: \"在此定义您的枚举\",\n    declare_array: \"声明数组\",\n    empty_index_name: \"在表 '{{tableName}}' 中声明了一个没有名称的索引\",\n    didnt_find_diagram: \"哎呀！找不到图表。\",\n    unsigned: \"无符号\",\n    share: \"分享\",\n    unshare: \"取消分享\",\n    copy_link: \"复制链接\",\n    readme: \"说明文档\",\n    failed_to_load: \"加载失败。请确认链接是否正确。\",\n    share_info:\n      \"* 分享此链接不会创建实时协作会话。\",\n    supported_types: \"支持的文件类型：\",\n    bulk_update: \"批量更新\",\n    multiselect: \"多选\",\n    dbml_view: \"DBML 视图\",\n    tab_view: \"标签视图\",\n    label: \"标签\",\n    many_side_label: \"多(n)侧标签\",\n    version: \"版本\",\n    versions: \"版本列表\",\n    no_saved_versions: \"暂无保存记录\",\n    record_version: \"记录版本\",\n    commited_at: \"提交于\",\n    read_only: \"只读\",\n    continue: \"继续\",\n    restore_version: \"还原版本\",\n    restore_warning: \"还原版本会覆盖所有更改。\",\n    return_to_current: \"返回当前图表\",\n    no_changes_to_record: \"没有可记录的变更\",\n    click_to_view: \"点击查看\",\n    load_more: \"加载更多\",\n    clear_cache: \"清除版本\",\n    cache_cleared: \"版本已清除\",\n    failed_to_record_version: \"记录版本失败\",\n    failed_to_load_diagram: \"加载图表失败\",\n    see_all: \"查看全部\",\n    snap_to_grid: \"对齐网格线\",\n  },\n};\n\nexport { zh, chinese };\n"
  },
  {
    "path": "src/i18n/utils/rtl.js",
    "content": "const rtlLanguages = [\"ar\", \"he\", \"fa\", \"ps\", \"ur\"];\nexport const isRtl = (language) => rtlLanguages.includes(language);\n"
  },
  {
    "path": "src/icons/IconAddArea.jsx",
    "content": "export default function IconAddArea() {\n  return (\n    <svg height=\"26\" width=\"26\">\n      <path\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"2\"\n        d=\"M4 2 L20 2 A4 4 0 0 1 22 4 L22 14 M14 22 L4 22 A4 4 0 0 1 1 18 L1 4 A4 4 0 0 1 5 2 M22 17 L22 25 M18 21 L26 21\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/icons/IconAddNote.jsx",
    "content": "export default function IconAddNote() {\n  return (\n    <svg height=\"26\" width=\"26\">\n      <path\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"2\"\n        d=\"M12 2 L20 2 A4 4 0 0 1 22 4 L22 14 M14 22 L4 22 A4 4 0 0 1 1 18 L1 12 L12 2 M1 12 L9 12 A3 3 0 0 0 12 9 L12 1 M22 17 L22 25 M18 21 L26 21\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/icons/IconAddTable.jsx",
    "content": "export default function IconAddTable() {\n  return (\n    <svg height=\"26\" width=\"26\">\n      <path\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"2\"\n        d=\"M4 2 L20 2 A4 4 0 0 1 22 4 L22 14 M14 22 L4 22 A4 4 0 0 1 1 18 L1 4 A4 4 0 0 1 5 2 M22 17 L22 25 M18 21 L26 21 M1 8 L22 8\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/icons/index.js",
    "content": "export { default as IconAddTable } from \"./IconAddTable\";\nexport { default as IconAddArea } from \"./IconAddArea\";\nexport { default as IconAddNote } from \"./IconAddNote\";\n"
  },
  {
    "path": "src/index.css",
    "content": "@import \"tailwindcss\";\n\n@config '../tailwind.config.js';\n\n/*\n  The default border color has changed to `currentColor` in Tailwind CSS v4,\n  so we've added these compatibility styles to make sure everything still\n  looks the same as it did with Tailwind CSS v3.\n\n  If we ever want to remove these styles, we need to add an explicit border\n  color utility to any element that depends on these defaults.\n*/\n@layer base {\n  *,\n  ::after,\n  ::before,\n  ::backdrop,\n  ::file-selector-button {\n    border-color: var(--color-gray-200, currentColor);\n  }\n}\n\n@layer base {\n  /*\n   * Workaround to allow proper bottom positioning for fixed\n   * elements in mobile browsers with collapsing url bars:\n   * https://stackoverflow.com/a/17555766/1137077\n   */\n  :root,\n  html,\n  body {\n    @apply h-full min-h-full;\n  }\n  #root {\n    @apply h-full min-h-full;\n  }\n}\n\n.semi-form-vertical .semi-form-field {\n  margin: 0;\n  padding-top: 8px !important;\n  padding-bottom: 8px !important;\n  overflow: hidden;\n}\n\n.semi-card .semi-collapse-item {\n  border: none !important;\n}\n\n.semi-button.semi-button-light {\n  background-color: rgba(var(--semi-grey-1), 1);\n}\n\n.semi-button.semi-button-light:hover {\n  background-color: rgba(var(--semi-grey-2), 1);\n}\n\n.semi-button.semi-button-primary:not(.semi-button-light):not(\n    .semi-button-borderless\n  ) {\n  background-color: rgba(var(--semi-blue-5), 1);\n}\n\n.semi-button.semi-button-primary:not(.semi-button-light):not(\n    .semi-button-borderless\n  ):hover {\n  background-color: rgba(var(--semi-blue-6), 1);\n}\n\n.semi-steps-item-content,\n.semi-steps-item-title {\n  width: 100% !important;\n}\n\n.semi-spin-wrapper {\n  color: inherit;\n}\n\n:disabled {\n  /* inherit Semi's cursor style for disabled elements */\n  cursor: inherit;\n}\n\n::-webkit-scrollbar {\n  width: 6px;\n  height: 6px;\n}\n\n::-webkit-scrollbar-track {\n  opacity: 0;\n}\n\n::-webkit-scrollbar-corner {\n  opacity: 0;\n}\n\n::-webkit-scrollbar-thumb {\n  background-color: rgba(var(--semi-grey-2), 1);\n  border-radius: 6px;\n}\n\n::-webkit-scrollbar-thumb:hover {\n  background-color: rgba(var(--semi-grey-3), 1);\n}\n\n.menu::-webkit-scrollbar-thumb {\n  background-color: rgba(var(--semi-grey-4), 1);\n}\n\n.theme {\n  color: var(--semi-color-text-1);\n  background-color: var(--semi-color-bg-0);\n}\n\n.sidesheet-theme {\n  color: var(--semi-color-text-1);\n  background-color: var(--semi-color-bg-2);\n}\n\n.popover-theme {\n  color: var(--semi-color-text-1);\n  background-color: var(--semi-color-bg-3);\n}\n\n.card-theme {\n  color: var(--semi-color-text-1);\n  background-color: rgba(var(--semi-grey-0), 1);\n}\n\n.toolbar-theme {\n  background-color: rgba(var(--semi-grey-1), 0.7);\n}\n\n.hover-1:hover {\n  background-color: rgba(var(--semi-grey-1), 1);\n}\n\n.bg-semi-grey-2 {\n  background-color: rgba(var(--semi-grey-2), 1);\n}\n\n.hover-2:hover {\n  background-color: rgba(var(--semi-grey-2), 1);\n}\n\n.text-color {\n  color: var(--semi-color-text-1);\n}\n\n.border-color {\n  border-color: rgba(var(--semi-grey-9), 0.08);\n}\n\n.table-border {\n  border-color: rgba(var(--semi-grey-2), 1);\n}\n\n.bg-dots {\n  background-color: white;\n  opacity: 0.8;\n  background-image: radial-gradient(rgb(118, 118, 209) 1px, white 1px);\n  background-size: 20px 20px;\n}\n\n.sliding-vertical span {\n  animation: top-to-bottom 9s linear infinite 0s;\n  -ms-animation: top-to-bottom 9s linear infinite 0s;\n  -webkit-animation: top-to-bottom 9s linear infinite 0s;\n  opacity: 0;\n  overflow: hidden;\n  position: absolute;\n}\n\n.sliding-vertical span:nth-child(2) {\n  animation-delay: 3s;\n  -ms-animation-delay: 3s;\n  -webkit-animation-delay: 3s;\n}\n.sliding-vertical span:nth-child(3) {\n  animation-delay: 6s;\n  -ms-animation-delay: 6s;\n  -webkit-animation-delay: 6s;\n}\n\n@keyframes top-to-bottom {\n  0% {\n    opacity: 0;\n  }\n  5% {\n    opacity: 0;\n    transform: translateY(-18px);\n  }\n  10% {\n    opacity: 1;\n    transform: translateY(0px);\n  }\n  25% {\n    opacity: 1;\n    transform: translateY(0px);\n  }\n  30% {\n    opacity: 0;\n    transform: translateY(18px);\n  }\n  80% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 0;\n  }\n}\n\n@keyframes dash-right {\n  100% {\n    stroke-dashoffset: -20;\n  }\n}\n\n.relationship-path {\n  stroke: grey;\n  stroke-width: 2.5;\n  fill: none;\n  stroke-linecap: butt;\n  transition: stroke 0.2s ease, stroke-width 0.2s ease;\n  pointer-events: stroke;\n}\n\n.group:hover .relationship-path {\n  stroke: #0084d1;\n  stroke-width: 6;\n  stroke-dasharray: 12 8;\n  animation: dash-right 1s linear infinite;\n  \n}\n"
  },
  {
    "path": "src/main.jsx",
    "content": "import ReactDOM from \"react-dom/client\";\nimport { LocaleProvider } from \"@douyinfe/semi-ui\";\nimport { Analytics } from \"@vercel/analytics/react\";\nimport App from \"./App.jsx\";\nimport en_US from \"@douyinfe/semi-ui/lib/es/locale/source/en_US\";\nimport \"./index.css\";\nimport \"./i18n/i18n.js\";\n\nconst root = ReactDOM.createRoot(document.getElementById(\"root\"));\nroot.render(\n  <LocaleProvider locale={en_US}>\n    <App />\n    <Analytics />\n  </LocaleProvider>,\n);\n"
  },
  {
    "path": "src/pages/BugReport.jsx",
    "content": "import { useEffect, useState, useCallback, useRef } from \"react\";\nimport logo_light from \"../assets/logo_light_160.png\";\nimport logo_dark from \"../assets/logo_dark_160.png\";\nimport { Banner, Button, Input, Upload, Toast, Spin } from \"@douyinfe/semi-ui\";\nimport { IconGithubLogo, IconPaperclip } from \"@douyinfe/semi-icons\";\nimport RichEditor from \"../components/LexicalEditor/RichEditor\";\nimport { LexicalComposer } from \"@lexical/react/LexicalComposer\";\nimport { editorConfig } from \"../data/editorConfig\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { $generateHtmlFromNodes } from \"@lexical/html\";\nimport { CLEAR_EDITOR_COMMAND } from \"lexical\";\nimport { Link } from \"react-router-dom\";\nimport { socials } from \"../data/socials\";\nimport { send } from \"../api/email\";\nimport { useSettings, useThemedPage } from \"../hooks\";\n\nfunction Form({ theme }) {\n  const [editor] = useLexicalComposerContext();\n  const [data, setData] = useState({\n    title: \"\",\n    attachments: [],\n  });\n  const [loading, setLoading] = useState(false);\n  const uploadRef = useRef();\n\n  const resetForm = () => {\n    setData({\n      title: \"\",\n      attachments: [],\n    });\n    setLoading(false);\n\n    if (uploadRef.current) {\n      uploadRef.current.clear();\n    }\n  };\n\n  const onFileChange = (fileList) => {\n    const attachments = [];\n\n    const processFile = (index) => {\n      const reader = new FileReader();\n\n      reader.onload = (event) => {\n        const dataUri = event.target.result;\n        attachments.push({ path: dataUri, filename: fileList[index].name });\n      };\n\n      reader.readAsDataURL(fileList[index].fileInstance);\n    };\n\n    fileList.forEach((_, i) => processFile(i));\n\n    setData((prev) => ({\n      ...prev,\n      attachments: attachments,\n    }));\n  };\n\n  const onSubmit = useCallback(() => {\n    setLoading(true);\n    editor.update(() => {\n      const sendMail = async () => {\n        try {\n          await send(\n            `[BUG REPORT]: ${data.title}`,\n            $generateHtmlFromNodes(editor),\n            data.attachments,\n          );\n          Toast.success(\"Bug reported!\");\n          editor.dispatchCommand(CLEAR_EDITOR_COMMAND, null);\n          resetForm();\n        } catch {\n          Toast.error(\"Oops! Something went wrong.\");\n          setLoading(false);\n        }\n      };\n      sendMail();\n    });\n  }, [editor, data]);\n\n  return (\n    <div className=\"p-5 mt-6 card-theme rounded-md\">\n      <Input\n        placeholder=\"Title\"\n        value={data.title}\n        onChange={(v) => setData((prev) => ({ ...prev, title: v }))}\n      />\n      <RichEditor theme={theme} placeholder=\"Describe the bug\" />\n      <Upload\n        action=\"#\"\n        ref={uploadRef}\n        onChange={(info) => onFileChange(info.fileList)}\n        beforeUpload={({ file }) => {\n          return {\n            autoRemove: false,\n            fileInstance: file.fileInstance,\n            status: \"success\",\n            shouldUpload: false,\n          };\n        }}\n        draggable={true}\n        dragMainText=\"Click to upload the file or drag and drop the file here\"\n        dragSubText=\"Upload up to 3 images\"\n        accept=\"image/*\"\n        limit={3}\n      />\n      <div className=\"pt-4 flex justify-end items-center\">\n        <div className=\"flex items-center\">\n          <Button\n            onClick={onSubmit}\n            style={{ padding: \"16px 24px\" }}\n            disabled={loading || data.title === \"\" || !data.title}\n          >\n            Submit\n          </Button>\n          <div className={loading ? \"ms-2\" : \"hidden\"}>\n            <Spin />\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n\nexport default function BugReport() {\n  const {\n    settings: { mode: theme },\n  } = useSettings();\n\n  useEffect(() => {\n    document.title = \"Report a bug | drawDB\";\n    document.body.setAttribute(\"class\", \"theme\");\n  }, []);\n\n  useThemedPage();\n\n  return (\n    <>\n      <div className=\"sm:py-3 py-5 px-20 sm:px-6 flex justify-between items-center\">\n        <div className=\"flex items-center justify-start\">\n          <Link to=\"/\">\n            <img\n              src={theme === \"dark\" ? logo_dark : logo_light}\n              alt=\"logo\"\n              className=\"me-2 sm:h-[28px] h-[42px]\"\n            />\n          </Link>\n          <div className=\"ms-4 sm:text-sm xl:text-lg font-semibold\">\n            Report a bug\n          </div>\n        </div>\n      </div>\n      <hr\n        className={`${\n          theme === \"dark\" ? \"border-zinc-700\" : \"border-zinc-300\"\n        } my-1`}\n      />\n      <div className=\"grid grid-cols-12 gap-8 my-6 mx-20 sm:mx-6\">\n        <div className=\"col-span-4 md:col-span-12 lg:col-span-4\">\n          <div className=\"card-theme p-6 rounded-md\">\n            <div className=\"flex items-center\">\n              <IconPaperclip />\n              <div className=\"font-bold ms-1\">Describe the bug </div>\n            </div>\n            <div className=\"text-sm mt-1\">\n              Please provide a clear and concise description of what the bug is.\n            </div>\n            <div className=\"flex items-center mt-3\">\n              <IconPaperclip />\n              <div className=\"font-bold ms-1\">Steps to reproduce the bug </div>\n            </div>\n            <div className=\"text-sm mt-1\">\n              Please provide the steps of how to reproduce the bug.\n            </div>\n            <div className=\"flex items-center mt-3\">\n              <IconPaperclip />\n              <div className=\"font-bold ms-1\">Expected behaviour</div>\n            </div>\n            <div className=\"text-sm mt-1\">\n              Tell us what you expected to see vs what you saw.\n            </div>\n            <div className=\"flex items-center mt-3\">\n              <IconPaperclip />\n              <div className=\"font-bold ms-1\">Your browser and device</div>\n            </div>\n            <div className=\"text-sm mt-1\">\n              What web browser and device did you encounter the bug on.\n            </div>\n            <div className=\"flex items-center mt-3\">\n              <IconPaperclip />\n              <div className=\"font-bold ms-1\">Screenshots</div>\n            </div>\n            <div className=\"text-sm mt-1\">\n              Add any relevant images if possible.\n            </div>\n            <div className=\"flex items-center justify-center my-2\">\n              <hr\n                className={`${\n                  theme === \"dark\" ? \"border-zinc-700\" : \"border-zinc-300\"\n                } grow`}\n              />\n              <div className=\"text-sm font-semibold m-2\">Alternatively</div>\n              <hr\n                className={`${\n                  theme === \"dark\" ? \"border-zinc-700\" : \"border-zinc-300\"\n                } grow`}\n              />\n            </div>\n            <Button\n              block\n              icon={<IconGithubLogo />}\n              style={{ backgroundColor: \"#239144\", color: \"white\" }}\n              onClick={() => {\n                window.open(`${socials.github}/issues`, \"_self\");\n              }}\n            >\n              Add an issue\n            </Button>\n          </div>\n        </div>\n        <div className=\"col-span-8 md:col-span-12 lg:col-span-8\">\n          <Banner\n            fullMode={false}\n            type=\"info\"\n            icon={null}\n            closeIcon={null}\n            description={\n              <div>\n                We value your feedback! If you&apos;ve encountered a bug or\n                issue while using our platform, please help us improve by\n                reporting it. Your input is invaluable in making our service\n                better.\n              </div>\n            }\n          />\n          <LexicalComposer initialConfig={editorConfig}>\n            <Form theme={theme} />\n          </LexicalComposer>\n        </div>\n      </div>\n      <hr\n        className={`${\n          theme === \"dark\" ? \"border-zinc-700\" : \"border-zinc-300\"\n        } my-1`}\n      />\n      <div className=\"text-center text-sm py-3\">\n        &copy; {new Date().getFullYear()} <strong>drawDB</strong> - All rights reserved.\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/pages/Editor.jsx",
    "content": "import LayoutContextProvider from \"../context/LayoutContext\";\nimport TransformContextProvider from \"../context/TransformContext\";\nimport TablesContextProvider from \"../context/DiagramContext\";\nimport UndoRedoContextProvider from \"../context/UndoRedoContext\";\nimport SelectContextProvider from \"../context/SelectContext\";\nimport AreasContextProvider from \"../context/AreasContext\";\nimport NotesContextProvider from \"../context/NotesContext\";\nimport TypesContextProvider from \"../context/TypesContext\";\nimport SaveStateContextProvider from \"../context/SaveStateContext\";\nimport EnumsContextProvider from \"../context/EnumsContext\";\nimport WorkSpace from \"../components/Workspace\";\nimport { useThemedPage } from \"../hooks\";\n\nexport default function Editor() {\n  useThemedPage();\n\n  return (\n    <LayoutContextProvider>\n      <TransformContextProvider>\n        <UndoRedoContextProvider>\n          <SelectContextProvider>\n            <AreasContextProvider>\n              <NotesContextProvider>\n                <TypesContextProvider>\n                  <EnumsContextProvider>\n                    <TablesContextProvider>\n                      <SaveStateContextProvider>\n                        <WorkSpace />\n                      </SaveStateContextProvider>\n                    </TablesContextProvider>\n                  </EnumsContextProvider>\n                </TypesContextProvider>\n              </NotesContextProvider>\n            </AreasContextProvider>\n          </SelectContextProvider>\n        </UndoRedoContextProvider>\n      </TransformContextProvider>\n    </LayoutContextProvider>\n  );\n}\n"
  },
  {
    "path": "src/pages/LandingPage.jsx",
    "content": "import { useState, useEffect } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport SimpleCanvas from \"../components/SimpleCanvas\";\nimport Navbar from \"../components/Navbar\";\nimport { diagram } from \"../data/heroDiagram\";\nimport mysql_icon from \"../assets/mysql.png\";\nimport postgres_icon from \"../assets/postgres.png\";\nimport sqlite_icon from \"../assets/sqlite.png\";\nimport mariadb_icon from \"../assets/mariadb.png\";\nimport oraclesql_icon from \"../assets/oraclesql.png\";\nimport sql_server_icon from \"../assets/sql-server.png\";\nimport discord from \"../assets/discord.png\";\nimport github from \"../assets/github.png\";\nimport warp from \"../assets/warp.png\";\nimport screenshot from \"../assets/screenshot.png\";\nimport FadeIn from \"../animations/FadeIn\";\nimport axios from \"axios\";\nimport { languages } from \"../i18n/i18n\";\nimport { Tweet } from \"react-tweet\";\nimport { socials } from \"../data/socials\";\n\nfunction shortenNumber(number) {\n  if (number < 1000) return number;\n\n  if (number >= 1000 && number < 1_000_000)\n    return `${(number / 1000).toFixed(1)}k`;\n}\n\nexport default function LandingPage() {\n  const [stats, setStats] = useState({ stars: 18000, forks: 1200 });\n\n  useEffect(() => {\n    const fetchStats = async () => {\n      await axios\n        .get(\"https://api.github-star-counter.workers.dev/user/drawdb-io\")\n        .then((res) => setStats(res.data));\n    };\n\n    document.body.setAttribute(\"theme-mode\", \"light\");\n    document.title =\n      \"drawDB | Online database diagram editor and SQL generator\";\n\n    fetchStats();\n  }, []);\n\n  return (\n    <div>\n      <div className=\"flex flex-col h-screen bg-zinc-100\">\n        <div className=\"text-white font-semibold py-1 text-sm text-center bg-linear-to-r from-[#12495e] from-10% via-slate-500 to-[#12495e]\" />\n\n        <FadeIn duration={0.6}>\n          <Navbar />\n        </FadeIn>\n\n        {/* Hero section */}\n        <div className=\"flex-1 flex-col relative mx-4 md:mx-0 mb-4 rounded-3xl bg-white\">\n          <div className=\"h-full md:hidden\">\n            <SimpleCanvas diagram={diagram} zoom={0.85} />\n          </div>\n          <div className=\"hidden md:block h-full bg-dots\" />\n          <div className=\"absolute left-12 w-[45%] top-[50%] translate-y-[-54%] md:left-[50%] md:translate-x-[-50%] p-8 md:p-3 md:w-full text-zinc-800\">\n            <FadeIn duration={0.75}>\n              <div className=\"md:px-3\">\n                <h1 className=\"text-[42px] md:text-3xl font-bold tracking-wide bg-linear-to-r from-sky-900 from-10% via-slate-500 to-[#12495e] inline-block text-transparent bg-clip-text\">\n                  Draw, Copy, and Paste\n                </h1>\n                <div className=\"text-lg font-medium mt-1 sliding-vertical\">\n                  Free and open source, simple, and intuitive database design\n                  editor, data-modeler, and SQL generator.{\" \"}\n                  <span className=\"ms-2 sm:block sm:ms-0 text-slate-500 bg-white font-bold whitespace-nowrap\">\n                    No sign up\n                  </span>\n                  <span className=\"ms-2 sm:block sm:ms-0 text-slate-500 bg-white font-bold whitespace-nowrap\">\n                    Free of charge\n                  </span>\n                  <span className=\"ms-2 sm:block sm:ms-0 text-slate-500 bg-white font-bold whitespace-nowrap\">\n                    Quick and easy\n                  </span>\n                </div>\n              </div>\n            </FadeIn>\n            <div className=\"mt-4 font-semibold md:mt-12\">\n              <button\n                className=\"py-3 mb-4 xl:mb-0 mr-4 transition-all duration-300 bg-white border rounded-full shadow-lg px-9 border-zinc-200 hover:bg-zinc-100 cursor-pointer\"\n                onClick={() =>\n                  document\n                    .getElementById(\"learn-more\")\n                    .scrollIntoView({ behavior: \"smooth\" })\n                }\n              >\n                Learn more\n              </button>\n              <Link\n                to=\"/editor\"\n                className=\"inline-block py-3 text-white transition-all duration-300 rounded-full shadow-lg bg-sky-900 ps-7 pe-6 hover:bg-sky-800\"\n              >\n                Try it for yourself <i className=\"bi bi-arrow-right ms-1\"></i>\n              </Link>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      {/* Learn more */}\n      <div id=\"learn-more\">\n        <div className=\"bg-zinc-100 py-10 px-28 md:px-8\">\n          {/* Supported by */}\n          <div className=\"text-center mb-16\">\n            <div className=\"text-2xl md:text-xl font-bold text-sky-800 mb-8\">\n              Supported by\n            </div>\n            <div>\n              <a\n                href=\"https://warp.dev/drawdb\"\n                target=\"_blank\"\n                rel=\"noreferrer\"\n              >\n                <img\n                  src={warp}\n                  alt=\"warp.dev\"\n                  width={260}\n                  className=\"m-auto mb-4\"\n                />\n                <div className=\"font-semibold text-lg md:text-base\">\n                  Next-gen AI-powered intelligent terminal for all platforms\n                </div>\n              </a>\n            </div>\n          </div>\n          <div className=\"mt-16 w-[75%] text-center sm:w-full mx-auto shadow-xs rounded-2xl border p-6 bg-white space-y-3 mb-12\">\n            <div className=\"text-lg font-medium\">\n              Build diagrams with a few clicks, see the full picture, export SQL\n              scripts, customize your editor, and more.\n            </div>\n            <img src={screenshot} className=\"mx-auto\" />\n          </div>\n          <div className=\"flex justify-center items-center gap-28 md:block\">\n            <div className=\"text-center mb-4\">\n              <div className=\"text-5xl md:text-3xl font-bold text-sky-800\">\n                {shortenNumber(stats.stars)}\n              </div>\n              <div className=\"ms-1 mt-1 font-medium tracking-wide\">\n                GitHub stars\n              </div>\n            </div>\n            <div className=\"text-center mb-4\">\n              <div className=\"text-5xl md:text-3xl font-bold text-sky-800\">\n                {shortenNumber(stats.forks)}\n              </div>\n              <div className=\"ms-1 mt-1 font-medium tracking-wide\">\n                GitHub forks\n              </div>\n            </div>\n            <div className=\"text-center mb-4\">\n              <div className=\"text-5xl md:text-3xl font-bold text-sky-800\">\n                {shortenNumber(languages.length)}\n              </div>\n              <div className=\"ms-1 mt-1 font-medium tracking-wide\">\n                Languages\n              </div>\n            </div>\n          </div>\n          <div className=\"text-lg font-medium text-center mt-12 mb-6\">\n            Design for your database\n          </div>\n          <div className=\"grid grid-cols-3 place-items-center sm:grid-cols-1 sm:gap-10\">\n            {dbs.map((s, i) => (\n              <img\n                key={\"icon-\" + i}\n                src={s.icon}\n                style={{ height: s.height }}\n                className=\"opacity-70 hover:opacity-100 transition-opacity duration-300 md:scale-[0.7] md:mx-auto\"\n              />\n            ))}\n          </div>\n        </div>\n        <svg\n          viewBox=\"0 0 1440 54\"\n          fill=\"none\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          width=\"100%\"\n          className=\"bg-transparent\"\n        >\n          <path\n            d=\"M0 54C0 54 320 0 720 0C1080 0 1440 54 1440 54V0H0V100Z\"\n            fill=\"#f4f4f5\"\n          />\n        </svg>\n      </div>\n\n      {/* Features */}\n      <div id=\"features\" className=\"py-8 px-36 md:px-8\">\n        <FadeIn duration={1}>\n          <div className=\"text-base font-medium text-center text-sky-900\">\n            More than just an editor\n          </div>\n          <div className=\"text-2xl mt-1 font-medium text-center\">\n            What drawDB has to offer\n          </div>\n          <div className=\"grid grid-cols-3 gap-8 mt-10 md:grid-cols-2 sm:grid-cols-1\">\n            {features.map((f, i) => (\n              <div\n                key={\"feature\" + i}\n                className=\"flex rounded-xl hover:bg-zinc-100 border border-zinc-100 shadow-xs hover:-translate-y-2 transition-all duration-300\"\n              >\n                <div className=\"bg-sky-700 px-0.5 rounded-l-xl\" />\n                <div className=\"px-8 py-4 \">\n                  <div className=\"text-lg font-semibold mb-3\">{f.title}</div>\n                  {f.content}\n                  <div className=\"mt-2 text-xs opacity-60\">{f.footer}</div>\n                </div>\n              </div>\n            ))}\n          </div>\n        </FadeIn>\n      </div>\n\n      {/* Tweets */}\n      <div className=\"px-40 mt-6 md:px-8\">\n        <div className=\"text-center text-2xl md:text-xl font-medium\">\n          What the internet says about us\n        </div>\n        <div\n          data-theme=\"light\"\n          className=\"grid grid-cols-2 place-items-center md:grid-cols-1\"\n        >\n          <Tweet id=\"1816111365125218343\" />\n          <Tweet id=\"1817933406337905021\" />\n          <Tweet id=\"1785457354777006524\" />\n          <Tweet id=\"1776842268042756248\" />\n        </div>\n      </div>\n\n      {/* Contact us */}\n      <svg\n        viewBox=\"0 0 1440 54\"\n        fill=\"none\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n        width=\"100%\"\n        className=\"bg-transparent -scale-100\"\n      >\n        <path\n          d=\"M0 48 C0 48 320 0 720 0C1080 0 1440 48 1440 48V0H0V100Z\"\n          fill=\"#f4f4f5\"\n        />\n      </svg>\n      <div className=\"bg-zinc-100 py-8 px-32 md:px-8\">\n        <div className=\"mt-4 mb-2 text-2xl font-bold text-center\">\n          Reach out to us\n        </div>\n        <div className=\"text-lg text-center mb-4\">\n          We love hearing from you. Join our community on Discord, GitHub, and\n          X.\n        </div>\n        <div className=\"px-36 text-center md:px-8\">\n          <div className=\"md:block md:space-y-3 flex gap-3 justify-center\">\n            <a\n              className=\"inline-block\"\n              href={socials.github}\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              <div className=\"bg-zinc-800 hover:opacity-90 transition-all duration-300 flex items-center gap-4 px-14 py-4 rounded-lg\">\n                <img src={github} className=\"h-8\" />\n                <div className=\"text-lg text-white font-bold\">\n                  See the source\n                </div>\n              </div>\n            </a>\n            <a\n              className=\"inline-block\"\n              href={socials.discord}\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              <div className=\"bg-[#5865f2] hover:opacity-90 transition-all duration-300 flex items-center gap-4 px-8 py-4 rounded-lg\">\n                <img src={discord} className=\"h-8\" />\n                <div className=\"text-lg text-white font-bold\">\n                  Join us on Discord\n                </div>\n              </div>\n            </a>\n            <a\n              className=\"inline-block\"\n              href={socials.twitter}\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              <div className=\"text-white bg-zinc-800 hover:opacity-90 transition-all duration-300 flex items-center gap-4 px-12 py-4 rounded-lg\">\n                <i className=\"text-2xl bi bi-twitter-x\" />\n                <div className=\"text-lg  font-bold\">Follow us on X</div>\n              </div>\n            </a>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"bg-red-700 py-1 text-center text-white text-xs font-semibold px-3\">\n        Attention! The diagrams are saved in your browser. Before clearing the\n        browser make sure to back up your data.\n      </div>\n      <hr className=\"border-zinc-300\" />\n      <div className=\"text-center text-sm py-3\">\n        &copy; {new Date().getFullYear()} <strong>drawDB</strong> - All rights\n        reserved.\n      </div>\n    </div>\n  );\n}\n\nconst dbs = [\n  { icon: mysql_icon, height: 80 },\n  { icon: postgres_icon, height: 48 },\n  { icon: sqlite_icon, height: 64 },\n  { icon: mariadb_icon, height: 64 },\n  { icon: sql_server_icon, height: 64 },\n  { icon: oraclesql_icon, height: 172 },\n];\n\nconst features = [\n  {\n    title: \"Export\",\n    content: (\n      <div>\n        Export the DDL script to run on your database or export the diagram as a\n        JSON or an image.\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Reverse engineer\",\n    content: (\n      <div>\n        Already have a schema? Import a DDL script to generate a diagram.\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Generate migrations\",\n    content: (\n      <div>\n        Version your diagram and generate migration scripts to update your\n        database\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Customizable workspace\",\n    content: (\n      <div>\n        Customize the UI to fit your preferences. Select the components you want\n        in your view.\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Keyboard shortcuts\",\n    content: (\n      <div>\n        Speed up development with keyboard shortcuts. See all available\n        shortcuts\n        <Link\n          to={`${socials.docs}/shortcuts`}\n          className=\"ms-1.5 text-blue-500 hover:underline\"\n        >\n          here\n        </Link>\n        .\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Templates\",\n    content: (\n      <div>\n        Start off with pre-built templates. Get a quick start or get inspiration\n        for your design.\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Custom Templates\",\n    content: (\n      <div>\n        Have boilerplate structures? Save time by saving them as templates and\n        load them when needed.\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Robust editor\",\n    content: (\n      <div>\n        Undo, redo, copy, paste, duplicate and more. Add tables, subject areas,\n        and notes.\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Issue detection\",\n    content: (\n      <div>\n        Detect and tackle errors in the diagram to make sure the scripts are\n        correct.\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Relational databases\",\n    content: (\n      <div>\n        We support 5 relational databases - MySQL, PostgreSQL, SQLite, MariaDB,\n        SQL Server.\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Object-Relational databases\",\n    content: (\n      <div>\n        Add custom types for object-relational databases, or create custom JSON\n        schemes.\n      </div>\n    ),\n    footer: \"\",\n  },\n  {\n    title: \"Presentation mode\",\n    content: (\n      <div>\n        Present your diagrams on a big screen during team meetings and\n        discussions.\n      </div>\n    ),\n    footer: \"\",\n  },\n];\n"
  },
  {
    "path": "src/pages/NotFound.jsx",
    "content": "import { socials } from \"../data/socials\";\n\nexport default function NotFound() {\n  return (\n    <div className=\"p-3 space-y-2\">\n      <p>hey there!</p>\n\n      <p>looking for something you couldn&apos;t find?</p>\n      <p>\n        check out the{\" \"}\n        <a className=\"text-blue-600\" href={socials.docs}>\n          docs\n        </a>\n        ,{\" \"}\n        <a className=\"text-blue-600\" href=\"mailto:drawdb@outlook.com\">\n          shoot us an email\n        </a>{\" \"}\n        or{\" \"}\n        <a className=\"text-blue-600\" href={socials.discord}>\n          a message on discord\n        </a>\n      </p>\n      <br />\n      <p className=\"opacity-70\">\n        * to create a relationship hold the blue dot of a field and drag it\n        towards the field you want to connect it to\n      </p>\n      <a\n        className=\"text-blue-600\"\n        href={`${socials.docs}/create-diagram#relationships`}\n      >\n        see here\n      </a>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/pages/Templates.jsx",
    "content": "import { useEffect } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { Tabs, TabPane, Banner, Steps } from \"@douyinfe/semi-ui\";\nimport { IconDeleteStroked } from \"@douyinfe/semi-icons\";\nimport { db } from \"../data/db\";\nimport { useLiveQuery } from \"dexie-react-hooks\";\nimport Thumbnail from \"../components/Thumbnail\";\nimport logo_light from \"../assets/logo_light_160.png\";\nimport template_screenshot from \"../assets/template_screenshot.png\";\n\nexport default function Templates() {\n  const defaultTemplates = useLiveQuery(() =>\n    db.templates.where({ custom: 0 }).toArray(),\n  );\n\n  const customTemplates = useLiveQuery(() =>\n    db.templates.where({ custom: 1 }).toArray(),\n  );\n\n  const deleteTemplate = async (id) => {\n    await db.templates.delete(id);\n  };\n\n  const forkTemplate = (id) => {\n    window.open(\"/editor/templates/\" + id, \"_blank\");\n  };\n\n  useEffect(() => {\n    document.title = \"Templates | drawDB\";\n  }, []);\n\n  return (\n    <div>\n      <div className=\"min-h-screen\">\n        <div className=\"sm:py-3 py-5 px-12 xl:px-20 sm:px-6 flex justify-between items-center select-none\">\n          <div className=\"flex items-center justify-start\">\n            <Link to=\"/\">\n              <img\n                src={logo_light}\n                alt=\"logo\"\n                className=\"me-2 sm:h-[28px] md:h-[46px] h-[48px]\"\n              />\n            </Link>\n            <div className=\"ms-4 sm:text-sm xl:text-xl text-xl font-semibold\">\n              Templates\n            </div>\n          </div>\n        </div>\n        <hr className=\"border-zinc-300\" />\n        <div className=\"xl:px-20 sm:px-6 px-12 py-6\">\n          <div className=\"w-full md:w-[75%] xl:w-[50%] mb-2\">\n            <div className=\"text-2xl sm:text-lg font-semibold mb-2 text-neutral-800\">\n              Database schema templates\n            </div>\n            <div className=\"text-sm text-neutral-700\">\n              A compilation of database entity relationship diagrams to give you\n              a quick start or inspire your application&apos;s architecture.\n            </div>\n          </div>\n          <Tabs>\n            <TabPane\n              tab={<span className=\"mx-2\">Default templates</span>}\n              itemKey=\"1\"\n            >\n              <div className=\"grid xl:grid-cols-3 grid-cols-2 sm:grid-cols-1 gap-10 my-6\">\n                {defaultTemplates?.map((t, i) => (\n                  <div\n                    key={t.id}\n                    className=\"bg-gray-100 hover:translate-y-[-6px] transition-all duration-300 border rounded-md\"\n                  >\n                    <div className=\"h-48\">\n                      <Thumbnail\n                        diagram={t}\n                        i={\"1\" + i}\n                        zoom={0.3}\n                        theme=\"light\"\n                      />\n                    </div>\n                    <div className=\"px-4 py-3\">\n                      <div className=\"flex justify-between\">\n                        <div className=\"text-lg font-bold text-zinc-700\">\n                          {t.title}\n                        </div>\n                        <button\n                          className=\"border rounded-sm px-2 py-1 bg-white hover:bg-gray-200 transition-all duration-300\"\n                          onClick={() => forkTemplate(t.templateId)}\n                        >\n                          <i className=\"fa-solid fa-code-fork\"></i>\n                        </button>\n                      </div>\n                      <div>{t.description}</div>\n                    </div>\n                  </div>\n                ))}\n              </div>\n            </TabPane>\n            <TabPane\n              tab={<span className=\"mx-2\">Your templates</span>}\n              itemKey=\"2\"\n            >\n              {customTemplates?.length > 0 ? (\n                <div className=\"grid xl:grid-cols-3 grid-cols-2 sm:grid-cols-1 gap-8 my-6\">\n                  {customTemplates?.map((c, i) => (\n                    <div\n                      key={c.id}\n                      className=\"bg-gray-100 hover:translate-y-[-6px] transition-all duration-300 border rounded-md\"\n                    >\n                      <div className=\"h-48\">\n                        <Thumbnail diagram={c} i={\"2\" + i} zoom={0.3} />\n                      </div>\n                      <div className=\"px-4 py-3 w-full\">\n                        <div className=\"flex justify-between\">\n                          <div className=\"text-lg font-bold text-zinc-700\">\n                            {c.title}\n                          </div>\n                          <div>\n                            <button\n                              className=\"me-1 border rounded-sm px-2 py-1 bg-white hover:bg-gray-200 transition-all duration-300\"\n                              onClick={() => forkTemplate(c.templateId)}\n                            >\n                              <i className=\"fa-solid fa-code-fork\"></i>\n                            </button>\n                          </div>\n                        </div>\n                        <div className=\"flex justify-around mt-2\">\n                          <button\n                            className=\"w-full text-center flex justify-center items-center border rounded-sm px-2 py-1 bg-white hover:bg-gray-200 transition-all duration-300 text-red-500\"\n                            onClick={() => deleteTemplate(c.id)}\n                          >\n                            <IconDeleteStroked />\n                            <div className=\"ms-1.5 font-semibold\">Delete</div>\n                          </button>\n                        </div>\n                      </div>\n                    </div>\n                  ))}\n                </div>\n              ) : (\n                <div className=\"py-5\">\n                  <Banner\n                    fullMode={false}\n                    type=\"info\"\n                    bordered\n                    icon={null}\n                    closeIcon={null}\n                    description={<div>You have no custom templates saved.</div>}\n                  />\n                  <div className=\"grid grid-cols-5 sm:grid-cols-1 gap-4 place-content-center my-4\">\n                    <img\n                      src={template_screenshot}\n                      className=\"border col-span-3 sm:cols-span-1 rounded-sm\"\n                    />\n                    <div className=\"col-span-2 sm:cols-span-1\">\n                      <div className=\"text-xl font-bold my-4\">\n                        How to save a template\n                      </div>\n                      <Steps direction=\"vertical\" style={{ margin: \"12px\" }}>\n                        <Steps.Step\n                          title=\"Build a diagram\"\n                          description=\"Build the template in the editor\"\n                        />\n                        <Steps.Step\n                          title=\"Save as template\"\n                          description=\"Editor > File > Save as template\"\n                        />\n                        <Steps.Step\n                          title=\"Load a template\"\n                          description=\"Fork a template to build on\"\n                        />\n                      </Steps>\n                    </div>\n                  </div>\n                </div>\n              )}\n            </TabPane>\n          </Tabs>\n        </div>\n      </div>\n      <hr className=\"border-zinc-300 my-1\" />\n      <div className=\"text-center text-sm py-3\">\n        &copy; {new Date().getFullYear()} <strong>drawDB</strong> - All rights\n        reserved.\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/templates/template1.js",
    "content": "import { Cardinality } from \"../data/constants\";\n\nexport const template1 = {\n  tables: [\n    {\n      id: 0,\n      name: \"users\",\n      x: 114.92525,\n      y: 281.2977500000002,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"username\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"password\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 255,\n        },\n        {\n          name: \"email\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: 255,\n        },\n        {\n          name: \"last_login\",\n          type: \"TIMESTAMP\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: \"\",\n          values: [],\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#6360f7\",\n    },\n    {\n      id: 1,\n      name: \"blog_posts\",\n      x: 277.57925,\n      y: 19.206750000000113,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"user_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"title\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 255,\n        },\n        {\n          name: \"content\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: 255,\n        },\n        {\n          name: \"cover\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#bc49c4\",\n    },\n    {\n      id: 2,\n      name: \"comments\",\n      x: 505.62112500000035,\n      y: 341.6078750000002,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"blog_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"user_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n        },\n        {\n          name: \"content\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#3cde7d\",\n    },\n    {\n      id: 3,\n      name: \"tags\",\n      x: 743.2832500000009,\n      y: 318.1841250000001,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#7d9dff\",\n    },\n    {\n      id: 4,\n      name: \"blog_tag\",\n      x: 812.1175000000004,\n      y: 131.55062500000008,\n      fields: [\n        {\n          name: \"blog_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"tag_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#ffe159\",\n    },\n  ],\n  relationships: [\n    {\n      startTableId: 1,\n      startFieldId: 1,\n      endTableId: 0,\n      endFieldId: 0,\n      name: \"blog_posts_user_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 0,\n    },\n    {\n      startTableId: 2,\n      startFieldId: 1,\n      endTableId: 1,\n      endFieldId: 0,\n      name: \"comments_blog_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 1,\n    },\n    {\n      startTableId: 2,\n      startFieldId: 2,\n      endTableId: 0,\n      endFieldId: 0,\n      name: \"comments_user_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 2,\n    },\n    {\n      startTableId: 4,\n      startFieldId: 1,\n      endTableId: 3,\n      endFieldId: 0,\n      name: \"blog_tag_tag_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 3,\n    },\n    {\n      startTableId: 4,\n      startFieldId: 0,\n      endTableId: 1,\n      endFieldId: 0,\n      name: \"blog_tag_blog_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 4,\n    },\n  ],\n  notes: [],\n  subjectAreas: [],\n  types: [],\n  title: \"Blog database schema\",\n  description:\n    \"A blog database including tables such as posts, users, comments, and tags to facilitate the storage and retrieval of blog-related information.\",\n  custom: 0,\n  templateId: crypto.randomUUID(),\n};\n"
  },
  {
    "path": "src/templates/template2.js",
    "content": "import { Cardinality } from \"../data/constants\";\n\nexport const template2 = {\n  tables: [\n    {\n      id: 0,\n      name: \"employees\",\n      x: 365,\n      y: 20,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"first_name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"last_name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 255,\n        },\n        {\n          name: \"dob\",\n          type: \"DATE\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: \"\",\n          values: [],\n        },\n        {\n          name: \"dep_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n        },\n        {\n          name: \"pos_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 5,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#a751e8\",\n    },\n    {\n      id: 1,\n      name: \"department\",\n      x: 41,\n      y: 59,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#6360f7\",\n    },\n    {\n      id: 2,\n      name: \"positions\",\n      x: 37,\n      y: 284,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"salary\",\n          type: \"DOUBLE\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: \"\",\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#3cde7d\",\n    },\n    {\n      id: 3,\n      name: \"projects\",\n      x: 668,\n      y: 28,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"description\",\n          type: \"TEXT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 65535,\n        },\n        {\n          name: \"start_date\",\n          type: \"DATE\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: \"\",\n          values: [],\n        },\n        {\n          name: \"end_date\",\n          type: \"DATE\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: \"\",\n          values: [],\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#7d9dff\",\n    },\n    {\n      id: 4,\n      name: \"project_assignment\",\n      x: 684,\n      y: 295,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"project_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"employee_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#32c9b0\",\n    },\n  ],\n  relationships: [\n    {\n      startTableId: 0,\n      startFieldId: 4,\n      endTableId: 1,\n      endFieldId: 0,\n      name: \"employees_dep_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 0,\n    },\n    {\n      startTableId: 0,\n      startFieldId: 5,\n      endTableId: 2,\n      endFieldId: 0,\n      name: \"employees_pos_id_fk\",\n      cardinality: Cardinality.ONE_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 1,\n    },\n    {\n      startTableId: 4,\n      startFieldId: 1,\n      endTableId: 3,\n      endFieldId: 0,\n      name: \"project_assignment_project_id_fk\",\n      cardinality: Cardinality.ONE_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 2,\n    },\n    {\n      startTableId: 4,\n      startFieldId: 2,\n      endTableId: 0,\n      endFieldId: 0,\n      name: \"project_assignment_employee_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 3,\n    },\n  ],\n  notes: [],\n  subjectAreas: [],\n  types: [],\n  title: \"Human resources schema\",\n  description:\n    \"A Human Resources (HR) schema designed to manage employee and project related information within an organization.\",\n  custom: 0,\n  templateId: crypto.randomUUID(),\n};\n"
  },
  {
    "path": "src/templates/template3.js",
    "content": "import { Cardinality } from \"../data/constants\";\n\nexport const template3 = {\n  tables: [\n    {\n      id: 0,\n      name: \"products\",\n      x: 331,\n      y: 300,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"description\",\n          type: \"TEXT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 65535,\n        },\n        {\n          name: \"price\",\n          type: \"DOUBLE\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: \"\",\n        },\n        {\n          name: \"category_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#32c9b0\",\n    },\n    {\n      id: 1,\n      name: \"categories\",\n      x: 649,\n      y: 391,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#89e667\",\n    },\n    {\n      id: 2,\n      name: \"orders\",\n      x: 756,\n      y: 47,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"date\",\n          type: \"DATETIME\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: \"\",\n          values: [],\n        },\n        {\n          name: \"customer_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n        },\n        {\n          name: \"amount\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n        },\n        {\n          name: \"status\",\n          type: \"ENUM\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          values: [\"delivered\", \"received\", \"processing\"],\n        },\n        {\n          name: \"product_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 5,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#6360f7\",\n    },\n    {\n      id: 3,\n      name: \"reviews\",\n      x: 33,\n      y: 93,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"customer_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"product_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n        },\n        {\n          name: \"rating\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n        },\n        {\n          name: \"content\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: 255,\n        },\n        {\n          name: \"date\",\n          type: \"DATETIME\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 5,\n          size: \"\",\n          values: [],\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#ffe159\",\n    },\n    {\n      id: 4,\n      name: \"customers\",\n      x: 402,\n      y: 16,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"address\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 255,\n        },\n        {\n          name: \"email\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: 255,\n        },\n        {\n          name: \"phone\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#ff4f81\",\n    },\n  ],\n  relationships: [\n    {\n      startTableId: 2,\n      startFieldId: 5,\n      endTableId: 0,\n      endFieldId: 0,\n      name: \"order_product_id_fk\",\n      cardinality: Cardinality.ONE_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 0,\n    },\n    {\n      startTableId: 0,\n      startFieldId: 4,\n      endTableId: 1,\n      endFieldId: 0,\n      name: \"products_category_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 1,\n    },\n    {\n      startTableId: 3,\n      startFieldId: 1,\n      endTableId: 4,\n      endFieldId: 0,\n      name: \"reviews_customer_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 2,\n    },\n    {\n      startTableId: 3,\n      startFieldId: 2,\n      endTableId: 0,\n      endFieldId: 0,\n      name: \"reviews_product_id_fk\",\n      cardinality: Cardinality.ONE_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 3,\n    },\n    {\n      startTableId: 2,\n      startFieldId: 2,\n      endTableId: 4,\n      endFieldId: 0,\n      name: \"orders_customer_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 4,\n    },\n  ],\n  notes: [],\n  subjectAreas: [],\n  types: [],\n  title: \"E-commerce schema\",\n  description:\n    \"An e-commerce schema designed to manage various aspects of an online store, including products, orders, and customers.\",\n  custom: 0,\n  templateId: crypto.randomUUID(),\n};\n"
  },
  {
    "path": "src/templates/template4.js",
    "content": "import { Cardinality } from \"../data/constants\";\n\nexport const template4 = {\n  tables: [\n    {\n      id: 0,\n      name: \"books\",\n      x: 167,\n      y: 88,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"title\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"isbn\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 255,\n        },\n        {\n          name: \"author_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n        },\n        {\n          name: \"genre_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#6360f7\",\n    },\n    {\n      id: 1,\n      name: \"genres\",\n      x: 78,\n      y: 379,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#bc49c4\",\n    },\n    {\n      id: 2,\n      name: \"authors\",\n      x: 475,\n      y: 342,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"birthday\",\n          type: \"DATE\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: \"\",\n          values: [],\n        },\n        {\n          name: \"nationality\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#ffe159\",\n    },\n    {\n      id: 3,\n      name: \"reservations\",\n      x: 501,\n      y: 14,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"book_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"patron_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n        },\n        {\n          name: \"date\",\n          type: \"DATE\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: \"\",\n          values: [],\n        },\n        {\n          name: \"email\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#89e667\",\n    },\n    {\n      id: 4,\n      name: \"patrons\",\n      x: 780,\n      y: 220,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"email\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 255,\n        },\n        {\n          name: \"phone\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#ff9159\",\n    },\n  ],\n  relationships: [\n    {\n      startTableId: 0,\n      startFieldId: 3,\n      endTableId: 2,\n      endFieldId: 0,\n      name: \"books_author_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 0,\n    },\n    {\n      startTableId: 3,\n      startFieldId: 1,\n      endTableId: 0,\n      endFieldId: 0,\n      name: \"reservations_book_id_fk\",\n      cardinality: Cardinality.ONE_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 1,\n    },\n    {\n      startTableId: 3,\n      startFieldId: 2,\n      endTableId: 4,\n      endFieldId: 0,\n      name: \"reservations_patron_id_fk\",\n      cardinality: Cardinality.ONE_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 2,\n    },\n    {\n      startTableId: 0,\n      startFieldId: 4,\n      endTableId: 1,\n      endFieldId: 0,\n      name: \"books_genre_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 3,\n    },\n  ],\n  notes: [],\n  subjectAreas: [],\n  types: [],\n  title: \"Library schema\",\n  description:\n    \"A library schema designed to manage the books, genres, reservations, and other aspects of a library system\",\n  custom: 0,\n  templateId: crypto.randomUUID(),\n};\n"
  },
  {
    "path": "src/templates/template5.js",
    "content": "import { Cardinality } from \"../data/constants\";\n\nexport const template5 = {\n  tables: [\n    {\n      id: 0,\n      name: \"accounts\",\n      x: 129,\n      y: 92,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"customer_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"type\",\n          type: \"ENUM\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          values: [\"checking\", \"savings\"],\n        },\n        {\n          name: \"number\",\n          type: \"BIGINT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n        },\n        {\n          name: \"balance\",\n          type: \"FLOAT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: \"\",\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#7d9dff\",\n    },\n    {\n      id: 1,\n      name: \"customers\",\n      x: 384,\n      y: 315,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"first_name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"last_name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 255,\n        },\n        {\n          name: \"phone\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: 255,\n        },\n        {\n          name: \"address\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#32c9b0\",\n    },\n    {\n      id: 2,\n      name: \"transactions\",\n      x: 431,\n      y: 4,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"account_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"time\",\n          type: \"DATETIME\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: \"\",\n          values: [],\n        },\n        {\n          name: \"type\",\n          type: \"ENUM\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          values: [\"withdrawal\", \"deposit\"],\n        },\n        {\n          name: \"amount\",\n          type: \"FLOAT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: \"\",\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#3cde7d\",\n    },\n    {\n      id: 3,\n      name: \"transfers\",\n      x: 112,\n      y: 358,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"from\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"to\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n        },\n        {\n          name: \"time\",\n          type: \"DATETIME\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: \"\",\n          values: [],\n        },\n        {\n          name: \"amount\",\n          type: \"FLOAT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: \"\",\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#89e667\",\n    },\n    {\n      id: 4,\n      name: \"cards\",\n      x: 772,\n      y: 29,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"type\",\n          type: \"ENUM\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          values: [\"visa\", \"master\"],\n        },\n        {\n          name: \"customer_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n        },\n        {\n          name: \"number\",\n          type: \"BIGINT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n        },\n        {\n          name: \"limit\",\n          type: \"FLOAT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: \"\",\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#ffe159\",\n    },\n    {\n      id: 5,\n      name: \"loans\",\n      x: 919,\n      y: 281,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"customer_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"amount\",\n          type: \"FLOAT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: \"\",\n        },\n        {\n          name: \"rate\",\n          type: \"FLOAT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: \"\",\n        },\n        {\n          name: \"term\",\n          type: \"DATE\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: \"\",\n          values: [],\n        },\n        {\n          name: \"status\",\n          type: \"ENUM\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 5,\n          values: [\"paid\", \"approved\"],\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#ff9159\",\n    },\n    {\n      id: 6,\n      name: \"investments\",\n      x: 664,\n      y: 395,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"customer_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"type\",\n          type: \"ENUM\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          values: [\"mutual-fund\", \"stock\"],\n        },\n        {\n          name: \"amount\",\n          type: \"FLOAT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: \"\",\n        },\n        {\n          name: \"date\",\n          type: \"DATE\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: \"\",\n          values: [],\n        },\n        {\n          name: \"current_val\",\n          type: \"FLOAT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 5,\n          size: \"\",\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#f03c3c\",\n    },\n  ],\n  relationships: [\n    {\n      startTableId: 0,\n      startFieldId: 1,\n      endTableId: 1,\n      endFieldId: 0,\n      name: \"accounts_customer_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 0,\n    },\n    {\n      startTableId: 4,\n      startFieldId: 2,\n      endTableId: 1,\n      endFieldId: 0,\n      name: \"cards_customer_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 1,\n    },\n    {\n      startTableId: 5,\n      startFieldId: 1,\n      endTableId: 1,\n      endFieldId: 0,\n      name: \"loans_customer_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 2,\n    },\n    {\n      startTableId: 6,\n      startFieldId: 1,\n      endTableId: 1,\n      endFieldId: 0,\n      name: \"investments_customer_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 3,\n    },\n    {\n      startTableId: 2,\n      startFieldId: 1,\n      endTableId: 0,\n      endFieldId: 0,\n      name: \"transactions_account_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 4,\n    },\n    {\n      startTableId: 3,\n      startFieldId: 2,\n      endTableId: 0,\n      endFieldId: 0,\n      name: \"transfers_to_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 5,\n    },\n    {\n      startTableId: 3,\n      startFieldId: 1,\n      endTableId: 0,\n      endFieldId: 0,\n      name: \"transfers_from_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 6,\n    },\n  ],\n  notes: [],\n  subjectAreas: [],\n  types: [],\n  title: \"Bank schema\",\n  description:\n    \"A financial schema designed to manage financial transactions, accounts, customers, and other aspects of financial data.\",\n  custom: 0,\n  templateId: crypto.randomUUID(),\n};\n"
  },
  {
    "path": "src/templates/template6.js",
    "content": "import { Cardinality } from \"../data/constants\";\n\nexport const template6 = {\n  tables: [\n    {\n      id: 0,\n      name: \"students\",\n      x: 200,\n      y: 10,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"first_name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"last_name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 255,\n        },\n        {\n          name: \"email\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: 255,\n        },\n        {\n          name: \"phone\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n          size: 255,\n        },\n        {\n          name: \"address\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 5,\n          size: 255,\n        },\n        {\n          name: \"dob\",\n          type: \"DATE\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 6,\n          size: \"\",\n          values: [],\n        },\n        {\n          name: \"major_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 7,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#ff4f81\",\n    },\n    {\n      id: 1,\n      name: \"courses\",\n      x: 477,\n      y: 354,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"dep_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n        },\n        {\n          name: \"credits\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#bc49c4\",\n    },\n    {\n      id: 2,\n      name: \"enrollment\",\n      x: 81,\n      y: 377,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"course_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n        },\n        {\n          name: \"student_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n        },\n        {\n          name: \"term\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#7c4af0\",\n    },\n    {\n      id: 3,\n      name: \"instructors\",\n      x: 771,\n      y: 50,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"first_name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"last_name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n          size: 255,\n        },\n        {\n          name: \"email\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 3,\n          size: 255,\n        },\n        {\n          name: \"dep_id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 4,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#7d9dff\",\n    },\n    {\n      id: 4,\n      name: \"departments\",\n      x: 785,\n      y: 338,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n        {\n          name: \"chairperson\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 2,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#32c9b0\",\n    },\n    {\n      id: 5,\n      name: \"major\",\n      x: 495,\n      y: 78,\n      fields: [\n        {\n          name: \"id\",\n          type: \"INT\",\n          default: \"\",\n          check: \"\",\n          primary: true,\n          unique: true,\n          notNull: true,\n          increment: true,\n          comment: \"\",\n          id: 0,\n        },\n        {\n          name: \"name\",\n          type: \"VARCHAR\",\n          default: \"\",\n          check: \"\",\n          primary: false,\n          unique: false,\n          notNull: false,\n          increment: false,\n          comment: \"\",\n          id: 1,\n          size: 255,\n        },\n      ],\n      comment: \"\",\n      indices: [],\n      color: \"#ffe159\",\n    },\n  ],\n  relationships: [\n    {\n      startTableId: 2,\n      startFieldId: 2,\n      endTableId: 0,\n      endFieldId: 0,\n      name: \"enrollment_student_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 0,\n    },\n    {\n      startTableId: 2,\n      startFieldId: 1,\n      endTableId: 1,\n      endFieldId: 0,\n      name: \"enrollment_course_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 1,\n    },\n    {\n      startTableId: 3,\n      startFieldId: 4,\n      endTableId: 4,\n      endFieldId: 0,\n      name: \"instructors_dep_id_fk\",\n      cardinality: Cardinality.ONE_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 2,\n    },\n    {\n      startTableId: 1,\n      startFieldId: 2,\n      endTableId: 4,\n      endFieldId: 0,\n      name: \"courses_dep_id_fk\",\n      cardinality: Cardinality.ONE_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 3,\n    },\n    {\n      startTableId: 0,\n      startFieldId: 7,\n      endTableId: 5,\n      endFieldId: 0,\n      name: \"students_major_id_fk\",\n      cardinality: Cardinality.MANY_TO_ONE,\n      updateConstraint: \"No action\",\n      deleteConstraint: \"No action\",\n      id: 4,\n    },\n  ],\n  notes: [],\n  subjectAreas: [],\n  types: [],\n  title: \"University schema\",\n  description:\n    \"A university schema designed to manage information about students, courses, instructors, and other aspects of university-related data.\",\n  custom: 0,\n  templateId: crypto.randomUUID(),\n};\n"
  },
  {
    "path": "src/utils/arrangeTables.js",
    "content": "import {\n  tableColorStripHeight,\n  tableFieldHeight,\n  tableHeaderHeight,\n} from \"../data/constants\";\n\nexport function arrangeTables(diagram) {\n  let maxHeight = -1;\n  const tableWidth = 200;\n  const gapX = 54;\n  const gapY = 40;\n  diagram.tables.forEach((table, i) => {\n    if (i < diagram.tables.length / 2) {\n      table.x = i * tableWidth + (i + 1) * gapX;\n      table.y = gapY;\n      const height =\n        table.fields.length * tableFieldHeight +\n        tableHeaderHeight +\n        tableColorStripHeight;\n      maxHeight = Math.max(height, maxHeight);\n    } else {\n      const index = diagram.tables.length - i - 1;\n      table.x = index * tableWidth + (index + 1) * gapX;\n      table.y = maxHeight + 2 * gapY;\n    }\n  });\n}\n"
  },
  {
    "path": "src/utils/cache.js",
    "content": "export const STORAGE_KEY = \"versions_cache\";\n\nexport function loadCache() {\n  try {\n    const saved = localStorage.getItem(STORAGE_KEY);\n    return saved ? JSON.parse(saved) : {};\n  } catch {\n    return {};\n  }\n}\n\nexport function saveCache(cache) {\n  localStorage.setItem(STORAGE_KEY, JSON.stringify(cache));\n}\n\nexport function deleteFromCache(key) {\n  const cache = loadCache();\n  if (cache[key]) {\n    delete cache[key];\n    saveCache(cache);\n  }\n}\n"
  },
  {
    "path": "src/utils/calcPath.js",
    "content": "import { tableFieldHeight, tableHeaderHeight } from \"../data/constants\";\nimport { getCommentHeight } from \"./utils\";\n\n/**\n * Generates an SVG path string to visually represent a relationship between two fields.\n *\n * @param {{\n *   startTable: { x: number, y: number },\n *   endTable: { x: number, y: number },\n *   startFieldIndex: number,\n *   endFieldIndex: number\n * }} r - Relationship data.\n * @param {number} tableWidth - Width of each table (used to calculate horizontal offsets).\n * @param {number} zoom - Zoom level (used to scale vertical spacing).\n * @returns {string} SVG path \"d\" attribute string.\n */\nexport function calcPath(r, tableWidth = 200, zoom = 1, showComments = true) {\n  if (!r) {\n    return \"\";\n  }\n\n  const width = tableWidth * zoom;\n  let x1 = r.startTable.x;\n  let y1 =\n    r.startTable.y +\n    r.startFieldIndex * tableFieldHeight +\n    tableHeaderHeight +\n    getCommentHeight(r.startTable.comment, tableWidth, showComments) +\n    tableFieldHeight / 2;\n  let x2 = r.endTable.x;\n  let y2 =\n    r.endTable.y +\n    r.endFieldIndex * tableFieldHeight +\n    getCommentHeight(r.endTable.comment, tableWidth, showComments) +\n    tableHeaderHeight +\n    tableFieldHeight / 2;\n\n  let radius = 10 * zoom;\n  const midX = (x2 + x1 + width) / 2;\n  const endX = x2 + width < x1 ? x2 + width : x2;\n\n  if (Math.abs(y1 - y2) <= 36 * zoom) {\n    radius = Math.abs(y2 - y1) / 3;\n    if (radius <= 2) {\n      if (x1 + width <= x2) return `M ${x1 + width} ${y1} L ${x2} ${y2 + 0.1}`;\n      else if (x2 + width < x1)\n        return `M ${x1} ${y1} L ${x2 + width} ${y2 + 0.1}`;\n    }\n  }\n\n  if (y1 <= y2) {\n    if (x1 + width <= x2) {\n      return `M ${x1 + width} ${y1} L ${\n        midX - radius\n      } ${y1} A ${radius} ${radius} 0 0 1 ${midX} ${y1 + radius} L ${midX} ${\n        y2 - radius\n      } A ${radius} ${radius} 0 0 0 ${midX + radius} ${y2} L ${endX} ${y2}`;\n    } else if (x2 <= x1 + width && x1 <= x2) {\n      return `M ${x1 + width} ${y1} L ${\n        x2 + width\n      } ${y1} A ${radius} ${radius} 0 0 1 ${x2 + width + radius} ${\n        y1 + radius\n      } L ${x2 + width + radius} ${y2 - radius} A ${radius} ${radius} 0 0 1 ${\n        x2 + width\n      } ${y2} L ${x2 + width} ${y2}`;\n    } else if (x2 + width >= x1 && x2 + width <= x1 + width) {\n      return `M ${x1} ${y1} L ${\n        x2 - radius\n      } ${y1} A ${radius} ${radius} 0 0 0 ${x2 - radius - radius} ${\n        y1 + radius\n      } L ${x2 - radius - radius} ${y2 - radius} A ${radius} ${radius} 0 0 0 ${\n        x2 - radius\n      } ${y2} L ${x2} ${y2}`;\n    } else {\n      return `M ${x1} ${y1} L ${\n        midX + radius\n      } ${y1} A ${radius} ${radius} 0 0 0 ${midX} ${y1 + radius} L ${midX} ${\n        y2 - radius\n      } A ${radius} ${radius} 0 0 1 ${midX - radius} ${y2} L ${endX} ${y2}`;\n    }\n  } else {\n    if (x1 + width <= x2) {\n      return `M ${x1 + width} ${y1} L ${\n        midX - radius\n      } ${y1} A ${radius} ${radius} 0 0 0 ${midX} ${y1 - radius} L ${midX} ${\n        y2 + radius\n      } A ${radius} ${radius} 0 0 1 ${midX + radius} ${y2} L ${endX} ${y2}`;\n    } else if (x1 + width >= x2 && x1 + width <= x2 + width) {\n      return `M ${x1} ${y1} L ${\n        x1 - radius - radius\n      } ${y1} A ${radius} ${radius} 0 0 1 ${x1 - radius - radius - radius} ${\n        y1 - radius\n      } L ${x1 - radius - radius - radius} ${\n        y2 + radius\n      } A ${radius} ${radius} 0 0 1 ${\n        x1 - radius - radius\n      } ${y2} L ${endX} ${y2}`;\n    } else if (x1 >= x2 && x1 <= x2 + width) {\n      return `M ${x1 + width} ${y1} L ${\n        x1 + width + radius\n      } ${y1} A ${radius} ${radius} 0 0 0 ${x1 + width + radius + radius} ${\n        y1 - radius\n      } L ${x1 + width + radius + radius} ${\n        y2 + radius\n      } A ${radius} ${radius} 0 0 0 ${x1 + width + radius} ${y2} L ${\n        x2 + width\n      } ${y2}`;\n    } else {\n      return `M ${x1} ${y1} L ${\n        midX + radius\n      } ${y1} A ${radius} ${radius} 0 0 1 ${midX} ${y1 - radius} L ${midX} ${\n        y2 + radius\n      } A ${radius} ${radius} 0 0 0 ${midX - radius} ${y2} L ${endX} ${y2}`;\n    }\n  }\n}\n"
  },
  {
    "path": "src/utils/diff.js",
    "content": "const isArrayOfObjects = (arr) =>\n  Array.isArray(arr) &&\n  arr.every((item) => typeof item === \"object\" && item !== null);\n\nconst isEmptyObject = (val) =>\n  typeof val === \"object\" &&\n  val !== null &&\n  !Array.isArray(val) &&\n  Object.keys(val).length === 0;\n\nexport const deepDiff = (\n  original = {},\n  modified = {},\n  acc,\n  keysToIgnore = [],\n  path = \"\",\n) => {\n  const keys = new Set([...Object.keys(original), ...Object.keys(modified)]);\n\n  for (const key of keys) {\n    if (keysToIgnore.includes(key)) continue;\n\n    const newPath = path ? `${path}#${key}` : key;\n    const origVal = original[key];\n    const modVal = modified[key];\n\n    if (isArrayOfObjects(origVal) || isArrayOfObjects(modVal)) {\n      const origArr = origVal ?? [];\n      const modArr = modVal ?? [];\n\n      for (const o of origArr) {\n        const m = modArr.find((x) => x.id === o.id);\n        if (m) {\n          deepDiff(\n            o,\n            m,\n            acc,\n            keysToIgnore,\n            `${newPath}[id=${o.id},name=${o.name}${o.type ? `,type=${o.type}` : \"\"}]`,\n          );\n        } else {\n          acc[\n            `${newPath}[id=${o.id},name=${o.name}${o.type ? `,type=${o.type}` : \"\"}]`\n          ] = {\n            from: o,\n            to: null,\n          };\n        }\n      }\n\n      for (const m of modArr) {\n        const o = origArr.find((x) => x.id === m.id);\n        if (!o) {\n          acc[\n            `${newPath}[id=${m.id},name=${m.name}${m.type ? `,type=${m.type}` : \"\"}]`\n          ] = {\n            from: null,\n            to: m,\n          };\n        }\n      }\n\n      continue;\n    }\n\n    if (Array.isArray(origVal) || Array.isArray(modVal)) {\n      if (JSON.stringify(origVal) !== JSON.stringify(modVal)) {\n        acc[newPath] = { from: origVal ?? null, to: modVal ?? null };\n      }\n      continue;\n    }\n\n    const isOrigObject = typeof origVal === \"object\" && origVal !== null;\n    const isModObject = typeof modVal === \"object\" && modVal !== null;\n\n    if (!isOrigObject && !isModObject) {\n      if (origVal !== modVal) {\n        acc[newPath] = {\n          from: origVal ?? null,\n          to: modVal ?? null,\n        };\n      }\n      continue;\n    }\n\n    if (isOrigObject && isModObject) {\n      if (isEmptyObject(origVal) && isEmptyObject(modVal)) {\n        continue;\n      }\n\n      deepDiff(origVal, modVal, acc, keysToIgnore, newPath);\n      continue;\n    }\n\n    acc[newPath] = {\n      from: origVal ?? null,\n      to: modVal ?? null,\n    };\n  }\n};\n"
  },
  {
    "path": "src/utils/exportAs/dbml.js",
    "content": "import { Cardinality } from \"../../data/constants\";\nimport { dbToTypes } from \"../../data/datatypes\";\nimport i18n from \"../../i18n/i18n\";\nimport { escapeQuotes } from \"../exportSQL/shared\";\nimport { isFunction, isKeyword } from \"../utils\";\n\nconst IDENT_SAFE_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nfunction escapeIdentifier(s) {\n  return String(s).replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\nfunction quoteIdentifier(name) {\n  if (name == null) return name;\n  const s = String(name);\n  return IDENT_SAFE_RE.test(s) ? s : `\"${escapeIdentifier(s)}\"`;\n}\n\nfunction parseDefaultDbml(field, database) {\n  if (isFunction(field.default)) {\n    return `\\`${field.default}\\``;\n  }\n\n  if (isKeyword(field.default) || !dbToTypes[database][field.type]?.hasQuotes) {\n    return field.default;\n  }\n\n  return `'${escapeQuotes(field.default)}'`;\n}\n\nfunction columnDefault(field, database) {\n  if (!field.default) {\n    return \"\";\n  }\n\n  if (typeof field.default === \"string\" && !field.default.trim()) {\n    return \"\";\n  }\n\n  return `default: ${parseDefaultDbml(field, database)}`;\n}\n\nfunction columnSettings(field, database) {\n  let constraints = [];\n\n  field.primary && constraints.push(\"pk\");\n  field.increment && constraints.push(\"increment\");\n  field.notNull && constraints.push(\"not null\");\n  field.unique && constraints.push(\"unique\");\n  constraints.push(columnDefault(field, database));\n  constraints.push(columnComment(field));\n\n  constraints = constraints.filter((x) => Boolean(x));\n\n  if (!constraints.length) {\n    return \"\";\n  }\n\n  return ` [ ${constraints.join(\", \")} ]`;\n}\n\nfunction cardinality(rel) {\n  switch (rel.cardinality) {\n    case i18n.t(Cardinality.ONE_TO_ONE):\n    case Cardinality.ONE_TO_ONE:\n      return \"-\";\n    case i18n.t(Cardinality.ONE_TO_MANY):\n    case Cardinality.ONE_TO_MANY:\n      return \"<\";\n    case i18n.t(Cardinality.MANY_TO_ONE):\n    case Cardinality.MANY_TO_ONE:\n      return \">\";\n  }\n}\n\nfunction fieldSize(field, database) {\n  const typeMetadata = dbToTypes[database][field.type];\n\n  if ((typeMetadata?.isSized || typeMetadata?.hasPrecision) && field.size)\n    return `(${field.size})`;\n\n  return \"\";\n}\n\nfunction processComment(comment) {\n  if (comment.includes(\"\\n\")) {\n    return `'''${comment}'''`;\n  }\n\n  return `'${escapeQuotes(comment)}'`;\n}\n\nfunction columnComment(field) {\n  if (!field.comment || field.comment.trim() === \"\") {\n    return \"\";\n  }\n\n  return `note: ${processComment(field.comment)}`;\n}\n\nfunction processType(type) {\n  // TODO: remove after a while\n  if (type.toUpperCase() === \"TIMESTAMP WITH TIME ZONE\") {\n    return \"timestamptz\";\n  }\n\n  return type.toLowerCase();\n}\n\nexport function toDBML(diagram) {\n  const generateRelString = (rel) => {\n    const { fields: startTableFields, name: startTableName } =\n      diagram.tables.find((t) => t.id === rel.startTableId);\n    const { name: startFieldName } = startTableFields.find(\n      (f) => f.id === rel.startFieldId,\n    );\n    const { fields: endTableFields, name: endTableName } = diagram.tables.find(\n      (t) => t.id === rel.endTableId,\n    );\n    const { name: endFieldName } = endTableFields.find(\n      (f) => f.id === rel.endFieldId,\n    );\n\n    return `Ref ${quoteIdentifier(rel.name)} {\\n\\t${quoteIdentifier(startTableName)}.${quoteIdentifier(startFieldName)} ${cardinality(rel)} ${quoteIdentifier(endTableName)}.${quoteIdentifier(endFieldName)} [ delete: ${rel.deleteConstraint.toLowerCase()}, update: ${rel.updateConstraint.toLowerCase()} ]\\n}`;\n  };\n\n  let enumDefinitions = \"\";\n\n  for (const table of diagram.tables) {\n    for (const field of table.fields) {\n      if (\n        (field.type === \"ENUM\" || field.type === \"SET\") &&\n        Array.isArray(field.values)\n      ) {\n        enumDefinitions += `enum ${quoteIdentifier(`${field.name}_${field.values.join(\"_\")}_t`)} {\\n\\t${field.values.map((v) => quoteIdentifier(v)).join(\"\\n\\t\")}\\n}\\n\\n`;\n      }\n    }\n  }\n\n  return `${diagram.enums\n    .map(\n      (en) =>\n        `enum ${quoteIdentifier(en.name)} {\\n${en.values.map((v) => `\\t${quoteIdentifier(v)}`).join(\"\\n\")}\\n}\\n\\n`,\n    )\n    .join(\"\\n\\n\")}${enumDefinitions}${diagram.tables\n    .map(\n      (table) =>\n        `Table ${quoteIdentifier(table.name)} [headercolor: ${table.color}] {\\n${table.fields\n          .map(\n            (field) =>\n              `\\t${quoteIdentifier(field.name)} ${\n                field.type === \"ENUM\" || field.type === \"SET\"\n                  ? quoteIdentifier(`${field.name}_${field.values.join(\"_\")}_t`)\n                  : processType(field.type)\n              }${fieldSize(\n                field,\n                diagram.database,\n              )}${columnSettings(field, diagram.database)}`,\n          )\n          .join(\"\\n\")}${\n          table.indices.length > 0\n            ? \"\\n\\n\\tindexes {\\n\" +\n              table.indices\n                .map(\n                  (index) =>\n                    `\\t\\t(${index.fields\n                      .map((f) => quoteIdentifier(f))\n                      .join(\", \")}) [ name: '${\n                      index.name\n                    }'${index.unique ? \", unique\" : \"\"} ]`,\n                )\n                .join(\"\\n\") +\n              \"\\n\\t}\"\n            : \"\"\n        }${\n          table.comment && table.comment.trim() !== \"\"\n            ? `\\n\\n\\tNote: ${processComment(table.comment)}`\n            : \"\"\n        }\\n}`,\n    )\n    .join(\"\\n\\n\")}\\n\\n${diagram.relationships\n    .map((rel) => generateRelString(rel))\n    .join(\"\\n\\n\")}`;\n}\n"
  },
  {
    "path": "src/utils/exportAs/documentation.js",
    "content": "import { dbToTypes } from \"../../data/datatypes\";\nimport { jsonToMermaid } from \"./mermaid\";\nimport { databases } from \"../../data/databases\";\n\nexport function jsonToDocumentation(obj) {\n  const documentationSummary = obj.tables\n    .map((table) => {\n      return `\\t- [${table.name}](#${table.name.toLowerCase()})`;\n    })\n    .join(\"\\n\");\n\n  const documentationEntities = obj.tables\n    .map((table) => {\n      let enums = \"\";\n      let indexes =\n        table.indices.length > 0\n          ? table.indices\n              .map((index) => {\n                return `| ${index.name} | ${index.unique ? \"✅\" : \"\"} | ${index.fields.join(\", \")} |`;\n              })\n              .join(\"\\n\")\n          : \"\";\n      const fields = table.fields\n        .map((field) => {\n          const fieldType =\n            field.type +\n            ((dbToTypes[obj.database][field.type].isSized ||\n              dbToTypes[obj.database][field.type].hasPrecision) &&\n            field.size &&\n            field.size !== \"\"\n              ? \"(\" + field.size + \")\"\n              : \"\");\n          enums +=\n            field.type === \"ENUM\" && field.values && field.values.length > 0\n              ? `##### ${field.name}\\n\\n${field.values.map((index) => `- ${index}`).join(\"\\n\")}\\n`\n              : \"\";\n          return (\n            `| **${field.name}** | ${fieldType} | ${field.primary ? \"🔑 PK, \" : \"\"}` +\n            `${field.notNull ? \"not null\" : \"null\"}${field.unique ? \", unique\" : \"\"}${field.increment ? \", autoincrement\" : \"\"}` +\n            `${field.default ? `, default: ${field.default}` : \"\"} | ` +\n            `${relationshipByField(table.id, obj.relationships, field.id)}` +\n            ` |${field.comment ? field.comment : \"\"} |`\n          );\n        })\n        .join(\"\\n\");\n      return (\n        `### ${table.name}\\n${table.comment ? table.comment : \"\"}\\n` +\n        `| Name        | Type          | Settings                      | References                    | Note                           |\\n` +\n        `|-------------|---------------|-------------------------------|-------------------------------|--------------------------------|\\n` +\n        `${fields} \\n${enums.length > 0 ? \"\\n#### Enums\\n\" + enums : \"\"}\\n` +\n        `${indexes.length > 0 ? \"\\n#### Indexes\\n| Name | Unique | Fields |\\n|------|--------|--------|\\n\" + indexes : \"\"}`\n      );\n    })\n    .join(\"\\n\");\n\n  function relationshipByField(table, relationships, fieldId) {\n    return relationships\n      .filter((r) => r.startTableId === table && r.startFieldId === fieldId)\n      .map((rel) => rel.name);\n  }\n\n  const documentationRelationships = obj.relationships?.length\n    ? obj.relationships\n        .map((r) => {\n          const startTable = obj.tables.find(\n            (t) => t.id === r.startTableId,\n          ).name;\n          const endTable = obj.tables.find((t) => t.id === r.endTableId).name;\n          return `- **${startTable} to ${endTable}**: ${r.cardinality}\\n`;\n        })\n        .join(\"\")\n    : \"\";\n\n  const documentationTypes =\n    databases[obj.database].hasTypes && obj.types.length > 0\n      ? obj.types\n          .map((type) => {\n            return (\n              `| Name        | fields        | Note                           |\\n` +\n              `|-------------|---------------|--------------------------------|\\n` +\n              `| ${type.name} | ${type.fields.map((field) => field.name).join(\", \")} | ${type.comment ? type.comment : \"\"} |`\n            );\n          })\n          .join(\"\\n\")\n      : \"\";\n\n  return (\n    `# ${obj.title} documentation\\n## Summary\\n\\n- [Introduction](#introduction)\\n- [Database Type](#database-type)\\n` +\n    `- [Table Structure](#table-structure)\\n${documentationSummary}\\n- [Relationships](#relationships)\\n- [Database Diagram](#database-diagram)\\n\\n` +\n    `## Introduction\\n\\n## Database type\\n\\n- **Database system:** ` +\n    `${databases[obj.database].name}\\n## Table structure\\n\\n${documentationEntities}` +\n    `\\n## Relationships\\n\\n${documentationRelationships}\\n` +\n    `${databases[obj.database].hasTypes && obj.types.length > 0 ? `## Types\\n\\n` + documentationTypes + `\\n\\n` : \"\"}` +\n    `## Database Diagram\\n\\n\\`\\`\\`mermaid\\n${jsonToMermaid(obj)}\\n\\`\\`\\``\n  );\n}\n"
  },
  {
    "path": "src/utils/exportAs/mermaid.js",
    "content": "import { Cardinality } from \"../../data/constants\";\nimport { dbToTypes } from \"../../data/datatypes\";\nimport i18n from \"../../i18n/i18n\";\n\nexport function jsonToMermaid(obj) {\n  function getMermaidRelationship(relationship) {\n    switch (relationship) {\n      case i18n.t(Cardinality.ONE_TO_ONE):\n      case Cardinality.ONE_TO_ONE:\n        return \"||--||\";\n      case i18n.t(Cardinality.MANY_TO_ONE_TO_ONE):\n      case Cardinality.MANY_TO_ONE:\n        return \"}o--||\";\n      case i18n.t(Cardinality.ONE_TO_MANY):\n      case Cardinality.ONE_TO_MANY:\n        return \"||--o{\";\n      default:\n        return \"--\";\n    }\n  }\n\n  const mermaidEntities = obj.tables\n    .map((table) => {\n      const fields = table.fields\n        .map((field) => {\n          const fieldType =\n            field.type +\n            ((dbToTypes[obj.database][field.type].isSized ||\n              dbToTypes[obj.database][field.type].hasPrecision) &&\n            field.size &&\n            field.size !== \"\"\n              ? \"(\" + field.size + \")\"\n              : \"\");\n          return `\\t\\t${fieldType} ${field.name}`;\n        })\n        .join(\"\\n\");\n      return `\\t${table.name} {\\n${fields}\\n\\t}`;\n    })\n    .join(\"\\n\\n\");\n\n  const mermaidRelationships = obj.relationships?.length\n    ? obj.relationships\n        .map((r) => {\n          const startTable = obj.tables.find(\n            (t) => t.id === r.startTableId,\n          ).name;\n          const endTable = obj.tables.find((t) => t.id === r.endTableId).name;\n          return `\\t${startTable} ${getMermaidRelationship(r.cardinality)} ${endTable} : references`;\n        })\n        .join(\"\\n\")\n    : \"\";\n\n  return `erDiagram\\n${mermaidRelationships ? `${mermaidRelationships}\\n\\n` : \"\"}${mermaidEntities}`;\n}\n"
  },
  {
    "path": "src/utils/exportSQL/generic.js",
    "content": "import { DB } from \"../../data/constants\";\nimport { dbToTypes, defaultTypes } from \"../../data/datatypes\";\nimport { escapeQuotes, getInlineFK, parseDefault } from \"./shared\";\n\nexport function getJsonType(f) {\n  if (!Object.keys(defaultTypes).includes(f.type)) {\n    return '{ \"type\" : \"object\", additionalProperties : true }';\n  }\n  switch (f.type) {\n    case \"INT\":\n    case \"SMALLINT\":\n    case \"BIGINT\":\n    case \"DECIMAL\":\n    case \"NUMERIC\":\n    case \"REAL\":\n    case \"FLOAT\":\n      return '{ \"type\" : \"number\" }';\n    case \"BOOLEAN\":\n      return '{ \"type\" : \"boolean\" }';\n    case \"JSON\":\n      return '{ \"type\" : \"object\", \"additionalProperties\" : true }';\n    case \"ENUM\":\n      return `{\\n\\t\\t\\t\\t\\t\"type\" : \"string\",\\n\\t\\t\\t\\t\\t\"enum\" : [${f.values\n        .map((v) => `\"${v}\"`)\n        .join(\", \")}]\\n\\t\\t\\t\\t}`;\n    case \"SET\":\n      return `{\\n\\t\\t\\t\\t\\t\"type\": \"array\",\\n\\t\\t\\t\\t\\t\"items\": {\\n\\t\\t\\t\\t\\t\\t\"type\": \"string\",\\n\\t\\t\\t\\t\\t\\t\"enum\": [${f.values\n        .map((v) => `\"${v}\"`)\n        .join(\", \")}]\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}`;\n    default:\n      return '{ \"type\" : \"string\"}';\n  }\n}\n\nexport function generateSchema(type) {\n  return `{\\n\\t\\t\\t\"$schema\": \"http://json-schema.org/draft-04/schema#\",\\n\\t\\t\\t\"type\": \"object\",\\n\\t\\t\\t\"properties\": {\\n\\t\\t\\t\\t${type.fields\n    .map((f) => `\"${f.name}\" : ${getJsonType(f)}`)\n    .join(\n      \",\\n\\t\\t\\t\\t\",\n    )}\\n\\t\\t\\t},\\n\\t\\t\\t\"additionalProperties\": false\\n\\t\\t}`;\n}\n\nexport function getTypeString(\n  field,\n  currentDb,\n  dbms = DB.MYSQL,\n  baseType = false,\n) {\n  if (dbms === DB.MYSQL) {\n    if (field.type === \"UUID\") {\n      return `VARCHAR(36)`;\n    }\n    if (\n      dbToTypes[currentDb][field.type].isSized ||\n      dbToTypes[currentDb][field.type].hasPrecision\n    ) {\n      return `${field.type}${field.size ? `(${field.size})` : \"\"}`;\n    }\n    if (field.type === \"SET\" || field.type === \"ENUM\") {\n      return `${field.type}(${field.values.map((v) => `\"${v}\"`).join(\", \")})`;\n    }\n    if (!Object.keys(defaultTypes).includes(field.type)) {\n      return \"JSON\";\n    }\n    return field.type;\n  } else if (dbms === DB.POSTGRES) {\n    if (field.type === \"SMALLINT\" && field.increment) {\n      return \"smallserial\";\n    }\n    if (field.type === \"INT\" && field.increment) {\n      return \"serial\";\n    }\n    if (field.type === \"BIGINT\" && field.increment) {\n      return \"bigserial\";\n    }\n    if (field.type === \"ENUM\") {\n      return `${field.name}_t`;\n    }\n    if (field.type === \"SET\") {\n      return `${field.name}_t[]`;\n    }\n    if (field.type === \"TIMESTAMP\") {\n      return \"TIMESTAMPTZ\";\n    }\n    if (field.type === \"DATETIME\") {\n      return `timestamp`;\n    }\n    if (dbToTypes[currentDb][field.type].isSized && field.size) {\n      const type =\n        field.type === \"BINARY\"\n          ? \"bit\"\n          : field.type === \"VARBINARY\"\n            ? \"bit varying\"\n            : field.type.toLowerCase();\n      return `${type}(${field.size})`;\n    }\n    if (\n      dbToTypes[currentDb][field.type].hasPrecision &&\n      field.size &&\n      field.size.trim() !== \"\"\n    ) {\n      return `${field.type.toLowerCase()}${field.size ? `(${field.size})` : \"\"}`;\n    }\n    return field.type.toLowerCase();\n  } else if (dbms === DB.MSSQL) {\n    let type = field.type;\n    switch (field.type) {\n      case \"ENUM\":\n        return baseType\n          ? \"NVARCHAR(255)\"\n          : `NVARCHAR(255) CHECK([${field.name}] in (${field.values\n              .map((v) => `'${v}'`)\n              .join(\", \")}))`;\n      case \"VARCHAR\":\n        type = `NVARCHAR`;\n        break;\n      case \"UUID\":\n        type = \"UNIQUEIDENTIFIER\";\n        break;\n      case \"DOUBLE\":\n        type = \"FLOAT\";\n        break;\n      case \"BOOLEAN\":\n        return \"BIT\";\n      case \"SET\":\n        return \"NVARCHAR(255)\";\n      case \"BLOB\":\n        return \"VARBINARY(MAX)\";\n      case \"JSON\":\n        return \"NVARCHAR(MAX)\";\n      case \"TEXT\":\n        return \"TEXT\";\n      default:\n        type = field.type;\n        break;\n    }\n    if (dbToTypes[currentDb][field.type].isSized) {\n      return `${type}(${field.size})`;\n    }\n\n    return type;\n  } else if (dbms === DB.ORACLESQL) {\n    let oracleType;\n    switch (field.type) {\n      case \"BIGINT\":\n        oracleType = \"NUMBER\";\n        break;\n      case \"VARCHAR\":\n        oracleType = \"VARCHAR2\";\n        break;\n      case \"TEXT\":\n        oracleType = \"CLOB\";\n        break;\n      case \"TIME\":\n      case \"DATETIME\":\n        oracleType = \"TIMESTAMP\";\n        break;\n      case \"BINARY\":\n      case \"VARBINARY\":\n        oracleType = \"RAW\";\n        break;\n      case \"UUID\":\n        oracleType = \"RAW(16)\";\n        break;\n      case \"SET\":\n      case \"ENUM\":\n        oracleType = field.name + \"_t\";\n        break;\n      default:\n        oracleType = field.type;\n        break;\n    }\n    const typeInfo = dbToTypes[currentDb][oracleType];\n    if (typeInfo.isSized || typeInfo.hasPrecision) {\n      if (oracleType === \"NUMBER\") {\n        return `${oracleType}${field.size ? `(${field.size})` : \"(38,0)\"}`;\n      } else {\n        return `${oracleType}${field.size ? `(${field.size})` : \"\"}`;\n      }\n    }\n\n    return oracleType;\n  }\n}\n\nexport function jsonToMySQL(obj) {\n  return `${obj.tables\n    .map(\n      (table) =>\n        `CREATE TABLE IF NOT EXISTS \\`${table.name}\\` (\\n${table.fields\n          .map(\n            (field) =>\n              `\\t\\`${\n                field.name\n              }\\` ${getTypeString(field, obj.database)}${field.notNull ? \" NOT NULL\" : \"\"}${\n                field.increment ? \" AUTO_INCREMENT\" : \"\"\n              }${field.unique ? \" UNIQUE\" : \"\"}${\n                field.default !== \"\"\n                  ? ` DEFAULT ${parseDefault(field, obj.database)}`\n                  : \"\"\n              }${\n                field.check === \"\" ||\n                !dbToTypes[obj.database][field.type].hasCheck\n                  ? !Object.keys(defaultTypes).includes(field.type)\n                    ? ` CHECK(\\n\\t\\tJSON_SCHEMA_VALID(\"${generateSchema(\n                        obj.types.find(\n                          (t) => t.name === field.type.toLowerCase(),\n                        ),\n                      )}\", \\`${field.name}\\`))`\n                    : \"\"\n                  : ` CHECK(${field.check})`\n              }${field.comment ? ` COMMENT '${escapeQuotes(field.comment)}'` : \"\"}`,\n          )\n          .join(\",\\n\")}${\n          table.fields.filter((f) => f.primary).length > 0\n            ? `,\\n\\tPRIMARY KEY(${table.fields\n                .filter((f) => f.primary)\n                .map((f) => `\\`${f.name}\\``)\n                .join(\", \")})`\n            : \"\"\n        }\\n)${table.comment ? ` COMMENT='${escapeQuotes(table.comment)}'` : \"\"};\\n${`\\n${table.indices\n          .map(\n            (i) =>\n              `CREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX \\`${i.name}\\`\\nON \\`${table.name}\\` (${i.fields\n                .map((f) => `\\`${f}\\``)\n                .join(\", \")});`,\n          )\n          .join(\"\\n\")}`}`,\n    )\n    .join(\"\\n\")}\\n${obj.references\n    .map((r) => {\n      const { name: startName, fields: startFields } = obj.tables.find(\n        (t) => t.id === r.startTableId,\n      );\n\n      const { name: endName, fields: endFields } = obj.tables.find(\n        (t) => t.id === r.endTableId,\n      );\n      return `ALTER TABLE \\`${startName}\\`\\nADD FOREIGN KEY(\\`${\n        startFields.find((f) => f.id === r.startFieldId).name\n      }\\`) REFERENCES \\`${endName}\\`(\\`${\n        endFields.find((f) => f.id === r.endFieldId).name\n      }\\`)\\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`;\n    })\n    .join(\"\\n\")}`;\n}\n\nexport function jsonToPostgreSQL(obj) {\n  return `${obj.types.map((type) => {\n    const typeStatements = type.fields\n      .filter((f) => f.type === \"ENUM\" || f.type === \"SET\")\n      .map(\n        (f) =>\n          `CREATE TYPE \"${f.name}_t\" AS ENUM (${f.values\n            .map((v) => `'${v}'`)\n            .join(\", \")});`,\n      )\n      .join(\"\\n\");\n    if (typeStatements.length > 0) {\n      return (\n        typeStatements.join(\"\") +\n        `${\n          type.comment === \"\" ? \"\" : `/**\\n${type.comment}\\n*/\\n`\n        }CREATE TYPE ${type.name} AS (\\n${type.fields\n          .map(\n            (f) => `\\t${f.name} ${getTypeString(f, obj.database, DB.POSTGRES)}`,\n          )\n          .join(\"\\n\")}\\n);`\n      );\n    } else {\n      return `CREATE TYPE ${type.name} AS (\\n${type.fields\n        .map(\n          (f) => `\\t${f.name} ${getTypeString(f, obj.database, DB.POSTGRES)}`,\n        )\n        .join(\",\\n\")}\\n);\\n${\n        type.comment && type.comment.trim() != \"\"\n          ? `\\nCOMMENT ON TYPE ${type.name} IS '${escapeQuotes(type.comment)}';\\n`\n          : \"\"\n      }`;\n    }\n  })}\\n${obj.tables\n    .map(\n      (table) =>\n        `${\n          table.fields.filter((f) => f.type === \"ENUM\" || f.type === \"SET\")\n            .length > 0\n            ? `${table.fields\n                .filter((f) => f.type === \"ENUM\" || f.type === \"SET\")\n                .map(\n                  (f) =>\n                    `CREATE TYPE \"${f.name}_t\" AS ENUM (${f.values\n                      .map((v) => `'${v}'`)\n                      .join(\", \")});\\n`,\n                )\n                .join(\"\\n\")}\\n`\n            : \"\"\n        }CREATE TABLE IF NOT EXISTS \"${table.name}\" (\\n${table.fields\n          .map(\n            (field) =>\n              `${field.comment === \"\" ? \"\" : `\\t-- ${field.comment}\\n`}\\t\"${\n                field.name\n              }\" ${getTypeString(field, obj.database, DB.POSTGRES)}${\n                field.notNull ? \" NOT NULL\" : \"\"\n              }${field.unique ? \" UNIQUE\" : \"\"}${\n                field.default !== \"\" ? ` DEFAULT ${parseDefault(field)}` : \"\"\n              }${\n                field.check === \"\" ||\n                !dbToTypes[obj.database][field.type].hasCheck\n                  ? \"\"\n                  : ` CHECK(${field.check})`\n              }`,\n          )\n          .join(\",\\n\")}${\n          table.fields.filter((f) => f.primary).length > 0\n            ? `,\\n\\tPRIMARY KEY(${table.fields\n                .filter((f) => f.primary)\n                .map((f) => `\"${f.name}\"`)\n                .join(\", \")})`\n            : \"\"\n        }\\n);\\n${table.comment != \"\" ? `\\nCOMMENT ON TABLE ${table.name} IS '${escapeQuotes(table.comment)}';\\n` : \"\"}${table.fields\n          .map((field) =>\n            field.comment.trim() !== \"\"\n              ? `COMMENT ON COLUMN ${table.name}.${field.name} IS '${escapeQuotes(field.comment)}';\\n`\n              : \"\",\n          )\n          .join(\"\")}\\n${table.indices\n          .map(\n            (i) =>\n              `CREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX \"${\n                i.name\n              }\"\\nON \"${table.name}\" (${i.fields\n                .map((f) => `\"${f}\"`)\n                .join(\", \")});`,\n          )\n          .join(\"\\n\")}`,\n    )\n    .join(\"\\n\")}\\n${obj.references\n    .map((r) => {\n      const { name: startName, fields: startFields } = obj.tables.find(\n        (t) => t.id === r.startTableId,\n      );\n\n      const { name: endName, fields: endFields } = obj.tables.find(\n        (t) => t.id === r.endTableId,\n      );\n      return `ALTER TABLE \"${startName}\"\\nADD FOREIGN KEY(\"${\n        startFields.find((f) => f.id === r.startFieldId).name\n      }\") REFERENCES \"${endName}\"(\"${\n        endFields.find((f) => f.id === r.endFieldId).name\n      }\")\\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`;\n    })\n    .join(\"\\n\")}`;\n}\n\nexport function getSQLiteType(field) {\n  switch (field.type) {\n    case \"INT\":\n    case \"SMALLINT\":\n    case \"BIGINT\":\n    case \"BOOLEAN\":\n      return \"INTEGER\";\n    case \"DECIMAL\":\n    case \"NUMERIC\":\n    case \"FLOAT\":\n    case \"DOUBLE\":\n    case \"REAL\":\n      return \"REAL\";\n    case \"CHAR\":\n    case \"VARCHAR\":\n    case \"UUID\":\n    case \"TEXT\":\n    case \"DATE\":\n    case \"TIME\":\n    case \"TIMESTAMP\":\n    case \"DATETIME\":\n    case \"BINARY\":\n    case \"VARBINARY\":\n      return \"TEXT\";\n    case \"ENUM\":\n      return `TEXT CHECK(\"${field.name}\" in (${field.values\n        .map((v) => `'${v}'`)\n        .join(\", \")}))`;\n    default:\n      return \"BLOB\";\n  }\n}\n\nexport function jsonToSQLite(obj) {\n  return obj.tables\n    .map((table) => {\n      const inlineFK = getInlineFK(table, obj);\n      return `${\n        table.comment === \"\" ? \"\" : `/* ${table.comment} */\\n`\n      }CREATE TABLE IF NOT EXISTS \"${table.name}\" (\\n${table.fields\n        .map(\n          (field) =>\n            `${field.comment === \"\" ? \"\" : `\\t-- ${field.comment}\\n`}\\t\"${\n              field.name\n            }\" ${getSQLiteType(field)}${field.notNull ? \" NOT NULL\" : \"\"}${\n              field.unique ? \" UNIQUE\" : \"\"\n            }${field.default !== \"\" ? ` DEFAULT ${parseDefault(field, obj.database)}` : \"\"}${\n              field.check === \"\" ||\n              !dbToTypes[obj.database][field.type].hasCheck\n                ? \"\"\n                : ` CHECK(${field.check})`\n            }`,\n        )\n        .join(\",\\n\")}${\n        table.fields.filter((f) => f.primary).length > 0\n          ? `,\\n\\tPRIMARY KEY(${table.fields\n              .filter((f) => f.primary)\n              .map((f) => `\"${f.name}\"`)\n              .join(\", \")})${inlineFK !== \"\" ? \",\\n\" : \"\"}`\n          : \"\"\n      }${inlineFK}\\n);\\n${table.indices\n        .map(\n          (i) =>\n            `\\nCREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX IF NOT EXISTS \"${\n              i.name\n            }\"\\nON \"${table.name}\" (${i.fields\n              .map((f) => `\"${f}\"`)\n              .join(\", \")});`,\n        )\n        .join(\"\\n\")}`;\n    })\n    .join(\"\\n\");\n}\n\nexport function jsonToMariaDB(obj) {\n  return `${obj.tables\n    .map(\n      (table) =>\n        `CREATE OR REPLACE TABLE \\`${table.name}\\` (\\n${table.fields\n          .map(\n            (field) =>\n              `\\t\\`${\n                field.name\n              }\\` ${getTypeString(field, obj.database, DB.MYSQL)}${field.notNull ? \" NOT NULL\" : \"\"}${\n                field.increment ? \" AUTO_INCREMENT\" : \"\"\n              }${field.unique ? \" UNIQUE\" : \"\"}${\n                field.default !== \"\"\n                  ? ` DEFAULT ${parseDefault(field, obj.database)}`\n                  : \"\"\n              }${\n                field.check === \"\" ||\n                !dbToTypes[obj.database][field.type].hasCheck\n                  ? !Object.keys(defaultTypes).includes(field.type)\n                    ? ` CHECK(\\n\\t\\tJSON_SCHEMA_VALID('${generateSchema(\n                        obj.types.find(\n                          (t) => t.name === field.type.toLowerCase(),\n                        ),\n                      )}', \\`${field.name}\\`))`\n                    : \"\"\n                  : ` CHECK(${field.check})`\n              }${field.comment ? ` COMMENT '${escapeQuotes(field.comment)}'` : \"\"}`,\n          )\n          .join(\",\\n\")}${\n          table.fields.filter((f) => f.primary).length > 0\n            ? `,\\n\\tPRIMARY KEY(${table.fields\n                .filter((f) => f.primary)\n                .map((f) => `\\`${f.name}\\``)\n                .join(\", \")})`\n            : \"\"\n        }\\n)${table.comment ? ` COMMENT='${escapeQuotes(table.comment)}'` : \"\"};${`\\n${table.indices\n          .map(\n            (i) =>\n              `CREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX \\`${\n                i.name\n              }\\`\\nON \\`${table.name}\\` (${i.fields\n                .map((f) => `\\`${f}\\``)\n                .join(\", \")});`,\n          )\n          .join(\"\\n\")}`}`,\n    )\n    .join(\"\\n\")}\\n${obj.references\n    .map((r) => {\n      const { name: startName, fields: startFields } = obj.tables.find(\n        (t) => t.id === r.startTableId,\n      );\n\n      const { name: endName, fields: endFields } = obj.tables.find(\n        (t) => t.id === r.endTableId,\n      );\n      return `ALTER TABLE \\`${startName}\\`\\nADD FOREIGN KEY(\\`${\n        startFields.find((f) => f.id === r.startFieldId).name\n      }\\`) REFERENCES \\`${endName}\\`(\\`${\n        endFields.find((f) => f.id === r.endFieldId).name\n      }\\`)\\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`;\n    })\n    .join(\"\\n\")}`;\n}\n\nexport function jsonToSQLServer(obj) {\n  return `${obj.types\n    .map((type) => {\n      return `${\n        type.comment === \"\" ? \"\" : `/**\\n${type.comment}\\n*/\\n`\n      }CREATE TYPE [${type.name}] FROM ${\n        type.fields.length < 0\n          ? \"\"\n          : `${getTypeString(type.fields[0], obj.database, DB.MSSQL, true)}`\n      };\\nGO\\n`;\n    })\n    .join(\"\\n\")}\\n${obj.tables\n    .map(\n      (table) =>\n        `${\n          table.comment === \"\" ? \"\" : `/**\\n${table.comment}\\n*/\\n`\n        }CREATE TABLE [${table.name}] (\\n${table.fields\n          .map(\n            (field) =>\n              `${field.comment === \"\" ? \"\" : `\\t-- ${field.comment}\\n`}\\t[${\n                field.name\n              }] ${getTypeString(field, obj.database, DB.MSSQL)}${\n                field.notNull ? \" NOT NULL\" : \"\"\n              }${field.increment ? \" IDENTITY\" : \"\"}${\n                field.unique ? \" UNIQUE\" : \"\"\n              }${\n                field.default !== \"\"\n                  ? ` DEFAULT ${parseDefault(field, obj.database)}`\n                  : \"\"\n              }${\n                field.check === \"\" ||\n                !dbToTypes[obj.database][field.type].hasCheck\n                  ? \"\"\n                  : ` CHECK(${field.check})`\n              }`,\n          )\n          .join(\",\\n\")}${\n          table.fields.filter((f) => f.primary).length > 0\n            ? `,\\n\\tPRIMARY KEY(${table.fields\n                .filter((f) => f.primary)\n                .map((f) => `[${f.name}]`)\n                .join(\", \")})`\n            : \"\"\n        }\\n);\\nGO\\n${table.indices\n          .map(\n            (i) =>\n              `\\nCREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX [${\n                i.name\n              }]\\nON [${table.name}] (${i.fields\n                .map((f) => `[${f}]`)\n                .join(\", \")});\\nGO\\n`,\n          )\n          .join(\"\")}`,\n    )\n    .join(\"\\n\")}\\n${obj.references\n    .map((r) => {\n      const { name: startName, fields: startFields } = obj.tables.find(\n        (t) => t.id === r.startTableId,\n      );\n\n      const { name: endName, fields: endFields } = obj.tables.find(\n        (t) => t.id === r.endTableId,\n      );\n      return `ALTER TABLE [${startName}]\\nADD FOREIGN KEY([${\n        startFields.find((f) => f.id === r.startFieldId).name\n      }]) REFERENCES [${endName}]([${\n        endFields.find((f) => f.id === r.endFieldId).name\n      }])\\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};\\nGO`;\n    })\n    .join(\"\\n\")}`;\n}\n\nexport function jsonToOracleSQL(obj) {\n  return `${obj.tables\n    .map(\n      (table) =>\n        `${\n          table.fields.filter((f) => f.type === \"ENUM\" || f.type === \"SET\")\n            .length > 0\n            ? `${table.fields\n                .filter((f) => f.type === \"ENUM\" || f.type === \"SET\")\n                .map(\n                  (f) =>\n                    `CREATE DOMAIN \"${f.name}_t\" AS ENUM (${f.values\n                      .map((v) => `'${v}'`)\n                      .join(\", \")});\\n`,\n                )\n                .join(\"\\n\")}\\n`\n            : \"\"\n        }${\n          table.comment === \"\" ? \"\" : `/* ${table.comment} */\\n`\n        }CREATE TABLE \"${table.name}\" (\\n${table.fields\n          .map(\n            (field) =>\n              `${field.comment === \"\" ? \"\" : `  -- ${field.comment}\\n`}  \"${\n                field.name\n              }\" ${getTypeString(field, obj.database, DB.ORACLESQL)}${\n                field.notNull ? \" NOT NULL\" : \"\"\n              }${field.increment ? \" GENERATED ALWAYS AS IDENTITY\" : \"\"}${\n                field.unique ? \" UNIQUE\" : \"\"\n              }${\n                field.default !== \"\"\n                  ? ` DEFAULT ${parseDefault(field, obj.database)}`\n                  : \"\"\n              }${\n                field.check === \"\" ||\n                !dbToTypes[obj.database][field.type].hasCheck\n                  ? \"\"\n                  : ` CHECK (${field.check})`\n              }`,\n          )\n          .join(\",\\n\")}${\n          table.fields.filter((f) => f.primary).length > 0\n            ? `,\\n  PRIMARY KEY (${table.fields\n                .filter((f) => f.primary)\n                .map((f) => `\"${f.name}\"`)\n                .join(\", \")})`\n            : \"\"\n        }\\n);\\n${table.indices\n          .map(\n            (i) =>\n              `\\nCREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX \"${i.name}\"\\n  ON \"${\n                table.name\n              }\" (${i.fields.map((f) => `\"${f}\"`).join(\", \")});`,\n          )\n          .join(\"\\n\")}`,\n    )\n    .join(\"\\n\\n\")}\\n${obj.references\n    .map((r) => {\n      const { name: startName, fields: startFields } = obj.tables.find(\n        (t) => t.id === r.startTableId,\n      );\n\n      const { name: endName, fields: endFields } = obj.tables.find(\n        (t) => t.id === r.endTableId,\n      );\n      return `ALTER TABLE \"${startName}\"\\nADD CONSTRAINT \"${r.name}\" FOREIGN KEY (\"${\n        startFields.find((f) => f.id === r.startFieldId).name\n      }\") REFERENCES \"${endName}\"(\"${\n        endFields.find((f) => f.id === r.endFieldId).name\n      }\");`;\n    })\n    .join(\"\\n\")}`;\n}\n"
  },
  {
    "path": "src/utils/exportSQL/index.js",
    "content": "import { DB } from \"../../data/constants\";\nimport { toMariaDB } from \"./mariadb\";\nimport { toMSSQL } from \"./mssql\";\nimport { toMySQL } from \"./mysql\";\nimport { toOracleSQL } from \"./oraclesql\";\nimport { toPostgres } from \"./postgres\";\nimport { toSqlite } from \"./sqlite\";\n\nexport function exportSQL(diagram) {\n  switch (diagram.database) {\n    case DB.SQLITE:\n      return toSqlite(diagram);\n    case DB.MYSQL:\n      return toMySQL(diagram);\n    case DB.POSTGRES:\n      return toPostgres(diagram);\n    case DB.MARIADB:\n      return toMariaDB(diagram);\n    case DB.MSSQL:\n      return toMSSQL(diagram);\n    case DB.ORACLESQL:\n      return toOracleSQL(diagram);\n    default:\n      return \"\";\n  }\n}\n"
  },
  {
    "path": "src/utils/exportSQL/mariadb.js",
    "content": "import { escapeQuotes, parseDefault } from \"./shared\";\n\nimport { dbToTypes } from \"../../data/datatypes\";\nimport { DB } from \"../../data/constants\";\n\nfunction parseType(field) {\n  let res = field.type;\n\n  if (field.type === \"SET\" || field.type === \"ENUM\") {\n    res += `${field.values ? \"(\" + field.values.map((value) => \"'\" + value + \"'\").join(\", \") + \")\" : \"\"}`;\n  }\n\n  if (dbToTypes[DB.MARIADB][field.type].isSized) {\n    res += `${field.size && field.size !== \"\" ? \"(\" + field.size + \")\" : \"\"}`;\n  }\n\n  return res;\n}\n\nexport function toMariaDB(diagram) {\n  return `${diagram.tables\n    .map(\n      (table) =>\n        `CREATE OR REPLACE TABLE \\`${table.name}\\` (\\n${table.fields\n          .map(\n            (field) =>\n              `\\t\\`${field.name}\\` ${parseType(field)}${field.unsigned ? \" UNSIGNED\" : \"\"}${field.notNull ? \" NOT NULL\" : \"\"}${\n                field.increment ? \" AUTO_INCREMENT\" : \"\"\n              }${field.unique ? \" UNIQUE\" : \"\"}${\n                field.default !== \"\"\n                  ? ` DEFAULT ${parseDefault(field, diagram.database)}`\n                  : \"\"\n              }${\n                field.check === \"\" ||\n                !dbToTypes[diagram.database][field.type].hasCheck\n                  ? \"\"\n                  : ` CHECK(${field.check})`\n              }${field.comment ? ` COMMENT '${escapeQuotes(field.comment)}'` : \"\"}`,\n          )\n          .join(\",\\n\")}${\n          table.fields.filter((f) => f.primary).length > 0\n            ? `,\\n\\tPRIMARY KEY(${table.fields\n                .filter((f) => f.primary)\n                .map((f) => `\\`${f.name}\\``)\n                .join(\", \")})`\n            : \"\"\n        }\\n)${table.comment ? ` COMMENT='${escapeQuotes(table.comment)}'` : \"\"};${`\\n${table.indices\n          .map(\n            (i) =>\n              `\\nCREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX \\`${\n                i.name\n              }\\`\\nON \\`${table.name}\\` (${i.fields\n                .map((f) => `\\`${f}\\``)\n                .join(\", \")});`,\n          )\n          .join(\"\")}`}`,\n    )\n    .join(\"\\n\")}\\n${diagram.references\n    .map((r) => {\n      const { name: startName, fields: startFields } = diagram.tables.find(\n        (t) => t.id === r.startTableId,\n      );\n\n      const { name: endName, fields: endFields } = diagram.tables.find(\n        (t) => t.id === r.endTableId,\n      );\n      return `ALTER TABLE \\`${startName}\\`\\nADD FOREIGN KEY(\\`${\n        startFields.find((f) => f.id === r.startFieldId).name\n      }\\`) REFERENCES \\`${endName}\\`(\\`${\n        endFields.find((f) => f.id === r.endFieldId).name\n      }\\`)\\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`;\n    })\n    .join(\"\\n\")}`;\n}\n"
  },
  {
    "path": "src/utils/exportSQL/mssql.js",
    "content": "import { parseDefault, escapeQuotes } from \"./shared\";\n\nimport { dbToTypes } from \"../../data/datatypes\";\nimport { DB } from \"../../data/constants\";\n\nfunction generateAddExtendedPropertySQL(value, level1name, level2name = null) {\n  if (!value || value.trim() === \"\") {\n    return \"\";\n  }\n  const escapedValue = escapeQuotes(value.replace(/\\n/g, \" \"));\n  const escapedTableName = escapeQuotes(level1name);\n\n  if (level2name) {\n    const escapedColumnName = escapeQuotes(level2name);\n    return `\nEXEC sys.sp_addextendedproperty\n    @name=N'MS_Description', @value=N'${escapedValue}',\n    @level0type=N'SCHEMA',@level0name=N'dbo',\n    @level1type=N'TABLE',@level1name=N'${escapedTableName}',\n    @level2type=N'COLUMN',@level2name=N'${escapedColumnName}';\nGO\n`;\n  } else {\n    return `\nEXEC sys.sp_addextendedproperty\n    @name=N'MS_Description', @value=N'${escapedValue}',\n    @level0type=N'SCHEMA',@level0name=N'dbo',\n    @level1type=N'TABLE',@level1name=N'${escapedTableName}';\nGO\n`;\n  }\n}\n\nexport function toMSSQL(diagram) {\n  const tablesSql = diagram.tables\n    .map((table) => {\n      const fieldsSql = table.fields\n        .map((field) => {\n          const typeMetaData = dbToTypes[DB.MSSQL][field.type.toUpperCase()];\n          const isSized = typeMetaData.isSized || typeMetaData.hasPrecision;\n\n          return `\\t[${field.name}] ${field.type}${field.size && isSized ? `(${field.size})` : \"\"}${\n            field.notNull ? \" NOT NULL\" : \"\"\n          }${field.increment ? \" IDENTITY\" : \"\"}${\n            field.unique ? \" UNIQUE\" : \"\"\n          }${\n            field.default !== \"\"\n              ? ` DEFAULT ${parseDefault(field, diagram.database)}`\n              : \"\"\n          }${\n            field.check === \"\" ||\n            !dbToTypes[diagram.database][field.type].hasCheck\n              ? \"\"\n              : ` CHECK(${field.check})`\n          }`;\n        })\n        .join(\",\\n\");\n\n      const primaryKeys = table.fields.filter((f) => f.primary);\n      const primaryKeySql =\n        primaryKeys.length > 0\n          ? `,\\n\\tPRIMARY KEY(${primaryKeys\n              .map((f) => `[${f.name}]`)\n              .join(\", \")})`\n          : \"\";\n\n      const createTableSql = `CREATE TABLE [${table.name}] (\\n${fieldsSql}${primaryKeySql}\\n);\\nGO\\n`;\n\n      const tableCommentSql = generateAddExtendedPropertySQL(\n        table.comment,\n        table.name,\n      );\n\n      const columnCommentsSql = table.fields\n        .map((field) =>\n          generateAddExtendedPropertySQL(field.comment, table.name, field.name),\n        )\n        .join(\"\");\n\n      const indicesSql = table.indices\n        .map(\n          (i) =>\n            `\\nCREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX [${\n              i.name\n            }]\\nON [${table.name}] (${i.fields\n              .map((f) => `[${f}]`)\n              .join(\", \")});\\nGO\\n`,\n        )\n        .join(\"\");\n\n      return `${createTableSql}${tableCommentSql}${columnCommentsSql}${indicesSql}`;\n    })\n    .join(\"\\n\");\n\n  const referencesSql = diagram.references\n    .map((r) => {\n      const startTable = diagram.tables.find((t) => t.id === r.startTableId);\n      const endTable = diagram.tables.find((t) => t.id === r.endTableId);\n\n      if (!startTable || !endTable) return \"\";\n\n      const startField = startTable.fields.find((f) => f.id === r.startFieldId);\n      const endField = endTable.fields.find((f) => f.id === r.endFieldId);\n\n      if (!startField || !endField) return \"\";\n\n      return `\\nALTER TABLE [${startTable.name}]\nADD FOREIGN KEY([${startField.name}])\nREFERENCES [${endTable.name}]([${endField.name}])\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};\nGO`;\n    })\n    .join(\"\");\n\n  return `${tablesSql}\\n${referencesSql}`;\n}\n"
  },
  {
    "path": "src/utils/exportSQL/mysql.js",
    "content": "import { escapeQuotes, parseDefault } from \"./shared\";\n\nimport { dbToTypes } from \"../../data/datatypes\";\nimport { DB } from \"../../data/constants\";\n\nfunction parseType(field) {\n  let res = field.type;\n\n  if (field.type === \"SET\" || field.type === \"ENUM\") {\n    res += `${field.values ? \"(\" + field.values.map((value) => \"'\" + value + \"'\").join(\", \") + \")\" : \"\"}`;\n  }\n\n  if (\n    dbToTypes[DB.MYSQL][field.type].isSized ||\n    dbToTypes[DB.MYSQL][field.type].hasPrecision\n  ) {\n    res += `${field.size && field.size !== \"\" ? \"(\" + field.size + \")\" : \"\"}`;\n  }\n\n  return res;\n}\n\nexport function toMySQL(diagram) {\n  return `${diagram.tables\n    .map(\n      (table) =>\n        `CREATE TABLE IF NOT EXISTS \\`${table.name}\\` (\\n${table.fields\n          .map(\n            (field) =>\n              `\\t\\`${field.name}\\` ${parseType(field)}${\n                dbToTypes[DB.MYSQL][field.type]?.signed && field.unsigned\n                  ? \" UNSIGNED\"\n                  : \"\"\n              }${field.notNull ? \" NOT NULL\" : \"\"}${\n                field.increment ? \" AUTO_INCREMENT\" : \"\"\n              }${field.unique ? \" UNIQUE\" : \"\"}${\n                field.default !== \"\"\n                  ? ` DEFAULT ${parseDefault(field, diagram.database)}`\n                  : \"\"\n              }${\n                field.check === \"\" ||\n                !dbToTypes[diagram.database][field.type].hasCheck\n                  ? \"\"\n                  : ` CHECK(${field.check})`\n              }${field.comment ? ` COMMENT '${escapeQuotes(field.comment)}'` : \"\"}`,\n          )\n          .join(\",\\n\")}${\n          table.fields.filter((f) => f.primary).length > 0\n            ? `,\\n\\tPRIMARY KEY(${table.fields\n                .filter((f) => f.primary)\n                .map((f) => `\\`${f.name}\\``)\n                .join(\", \")})`\n            : \"\"\n        }\\n)${table.comment ? ` COMMENT='${escapeQuotes(table.comment)}'` : \"\"};\\n${`\\n${table.indices\n          .map(\n            (i) =>\n              `\\nCREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX \\`${\n                i.name\n              }\\`\\nON \\`${table.name}\\` (${i.fields\n                .map((f) => `\\`${f}\\``)\n                .join(\", \")});`,\n          )\n          .join(\"\")}`}`,\n    )\n    .join(\"\\n\")}\\n${diagram.references\n    .map((r) => {\n      const { name: startName, fields: startFields } = diagram.tables.find(\n        (t) => t.id === r.startTableId,\n      );\n\n      const { name: endName, fields: endFields } = diagram.tables.find(\n        (t) => t.id === r.endTableId,\n      );\n      return `ALTER TABLE \\`${startName}\\`\\nADD FOREIGN KEY(\\`${\n        startFields.find((f) => f.id === r.startFieldId).name\n      }\\`) REFERENCES \\`${endName}\\`(\\`${\n        endFields.find((f) => f.id === r.endFieldId).name\n      }\\`)\\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`;\n    })\n    .join(\"\\n\")}`;\n}\n"
  },
  {
    "path": "src/utils/exportSQL/oraclesql.js",
    "content": "import { dbToTypes } from \"../../data/datatypes\";\nimport { parseDefault } from \"./shared\";\n\nexport function toOracleSQL(diagram) {\n  return `${diagram.tables\n    .map(\n      (table) =>\n        `${\n          table.comment === \"\" ? \"\" : `/* ${table.comment} */\\n`\n        }CREATE TABLE \"${table.name}\" (\\n${table.fields\n          .map(\n            (field) =>\n              `${field.comment === \"\" ? \"\" : `\\t-- ${field.comment}\\n`}\\t\"${\n                field.name\n              }\" ${field.type}${\n                field.size !== undefined && field.size !== \"\"\n                  ? \"(\" + field.size + \")\"\n                  : \"\"\n              }${field.notNull ? \" NOT NULL\" : \"\"}${\n                field.increment ? \" GENERATED ALWAYS AS IDENTITY\" : \"\"\n              }${field.unique ? \" UNIQUE\" : \"\"}${\n                field.default !== \"\"\n                  ? ` DEFAULT ${parseDefault(field, diagram.database)}`\n                  : \"\"\n              }${\n                field.check === \"\" ||\n                !dbToTypes[diagram.database][field.type].hasCheck\n                  ? \"\"\n                  : ` CHECK(${field.check})`\n              }${field.comment ? ` -- ${field.comment}` : \"\"}`,\n          )\n          .join(\",\\n\")}${\n          table.fields.filter((f) => f.primary).length > 0\n            ? `,\\n\\tPRIMARY KEY(${table.fields\n                .filter((f) => f.primary)\n                .map((f) => `\"${f.name}\"`)\n                .join(\", \")})`\n            : \"\"\n        }\\n)${table.comment ? ` -- ${table.comment}` : \"\"};\\n${`\\n${table.indices\n          .map(\n            (i) =>\n              `\\nCREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX \"${i.name}\"\\nON \"${table.name}\" (${i.fields\n                .map((f) => `\"${f}\"`)\n                .join(\", \")});`,\n          )\n          .join(\"\")}`}`,\n    )\n    .join(\"\\n\")}\\n${diagram.references\n    .map((r) => {\n      const { name: startName, fields: startFields } = diagram.tables.find(\n        (t) => t.id === r.startTableId,\n      );\n      const { name: endName, fields: endFields } = diagram.tables.find(\n        (t) => t.id === r.endTableId,\n      );\n      return `ALTER TABLE \"${startName}\"\\nADD CONSTRAINT \"${r.name}\" FOREIGN KEY (\"${\n        startFields.find((f) => f.id === r.startFieldId).name\n      }\") REFERENCES \"${endName}\" (\"${\n        endFields.find((f) => f.id === r.endFieldId).name\n      }\")\\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`;\n    })\n    .join(\"\\n\")}`;\n}\n"
  },
  {
    "path": "src/utils/exportSQL/postgres.js",
    "content": "import { escapeQuotes, exportFieldComment, parseDefault } from \"./shared\";\nimport { dbToTypes } from \"../../data/datatypes\";\n\nexport function toPostgres(diagram) {\n  const enumStatements = diagram.enums\n    .map(\n      (e) =>\n        `CREATE TYPE \"${e.name}\" AS ENUM (\\n${e.values\n          .map((v) => `\\t'${v}'`)\n          .join(\",\\n\")}\\n);\\n`,\n    )\n    .join(\"\\n\");\n\n  const typeStatements = diagram.types\n    .map(\n      (type) =>\n        `CREATE TYPE ${type.name} AS (\\n${type.fields\n          .map((f) => `\\t${f.name} ${f.type}`)\n          .join(\",\\n\")}\\n);\\n\\n${\n          type.comment?.trim()\n            ? `COMMENT ON TYPE \"${type.name}\" IS '${escapeQuotes(type.comment)}';\\n`\n            : \"\"\n        }`,\n    )\n    .join(\"\\n\");\n\n  const tableStatements = diagram.tables\n    .map((table) => {\n      const inheritsClause =\n        Array.isArray(table.inherits) && table.inherits.length > 0\n          ? `\\n) INHERITS (${table.inherits.map((parent) => `\"${parent}\"`).join(\", \")})`\n          : \"\\n)\";\n\n      const fieldDefinitions = table.fields\n        .map(\n          (field) =>\n            `${exportFieldComment(field.comment)}\\t\"${\n              field.name\n            }\" ${field.type}${\n              field.size ? `(${field.size})` : \"\"\n            }${field.isArray ? \" ARRAY\" : \"\"}${field.notNull ? \" NOT NULL\" : \"\"}${\n              field.unique ? \" UNIQUE\" : \"\"\n            }${field.increment ? \" GENERATED BY DEFAULT AS IDENTITY\" : \"\"}${\n              field.default?.trim()\n                ? ` DEFAULT ${parseDefault(field, diagram.database)}`\n                : \"\"\n            }${\n              field.check && dbToTypes[diagram.database][field.type]?.hasCheck\n                ? ` CHECK(${field.check})`\n                : \"\"\n            }`,\n        )\n        .join(\",\\n\");\n\n      const primaryKeyClause = table.fields.some((f) => f.primary)\n        ? `,\\n\\tPRIMARY KEY(${table.fields\n            .filter((f) => f.primary)\n            .map((f) => `\"${f.name}\"`)\n            .join(\", \")})`\n        : \"\";\n\n      const commentStatements = [\n        table.comment?.trim()\n          ? `COMMENT ON TABLE \"${table.name}\" IS '${escapeQuotes(table.comment)}';`\n          : \"\",\n        ...table.fields\n          .map((field) =>\n            field.comment?.trim()\n              ? `COMMENT ON COLUMN \"${table.name}\".\"${field.name}\" IS '${escapeQuotes(field.comment)}';`\n              : \"\",\n          )\n          .filter(Boolean),\n      ].join(\"\\n\");\n\n      const indexStatements = table.indices\n        .map(\n          (i) =>\n            `CREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX \"${i.name}\"\\nON \"${table.name}\" (${i.fields\n              .map((f) => `\"${f}\"`)\n              .join(\", \")});`,\n        )\n        .join(\"\\n\");\n\n      return `CREATE TABLE IF NOT EXISTS \"${table.name}\" (\\n${fieldDefinitions}${primaryKeyClause}${inheritsClause};\\n\\n${commentStatements}\\n${indexStatements}`;\n    })\n    .join(\"\\n\\n\");\n\n  const foreignKeyStatements = diagram.references\n    .map((r) => {\n      const startTable = diagram.tables.find((t) => t.id === r.startTableId);\n      const endTable = diagram.tables.find((t) => t.id === r.endTableId);\n      const startField = startTable?.fields.find(\n        (f) => f.id === r.startFieldId,\n      );\n      const endField = endTable?.fields.find((f) => f.id === r.endFieldId);\n\n      if (!startTable || !endTable || !startField || !endField) return \"\";\n\n      return `ALTER TABLE \"${startTable.name}\"\\nADD FOREIGN KEY(\"${startField.name}\") REFERENCES \"${endTable.name}\"(\"${endField.name}\")\\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`;\n    })\n    .filter(Boolean)\n    .join(\"\\n\");\n\n  return [\n    enumStatements,\n    enumStatements.trim() && typeStatements\n      ? \"\\n\" + typeStatements\n      : typeStatements,\n    tableStatements,\n    foreignKeyStatements,\n  ]\n    .filter(Boolean)\n    .join(\"\\n\");\n}\n"
  },
  {
    "path": "src/utils/exportSQL/shared.js",
    "content": "import { isFunction, isKeyword } from \"../utils\";\n\nimport { DB } from \"../../data/constants\";\nimport { dbToTypes } from \"../../data/datatypes\";\n\nexport function parseDefault(field, database = DB.GENERIC) {\n  if (\n    isFunction(field.default) ||\n    isKeyword(field.default) ||\n    !dbToTypes[database][field.type].hasQuotes\n  ) {\n    return field.default;\n  }\n\n  return `'${escapeQuotes(field.default)}'`;\n}\n\nexport function escapeQuotes(str) {\n  return str.replace(/[']/g, \"'$&\");\n}\n\nexport function exportFieldComment(comment) {\n  if (comment === \"\") {\n    return \"\";\n  }\n\n  return comment\n    .split(\"\\n\")\n    .map((commentLine) => `\\t-- ${commentLine}\\n`)\n    .join(\"\");\n}\n\nexport function getInlineFK(table, obj) {\n  let fks = [];\n  obj.references.forEach((r) => {\n    if (r.startTableId === table.id) {\n      fks.push(\n        `\\tFOREIGN KEY (\"${table.fields.find((f) => f.id === r.startFieldId)?.name}\") REFERENCES \"${\n          obj.tables.find((t) => t.id === r.endTableId)?.name\n        }\"(\"${\n          obj.tables\n            .find((t) => t.id === r.endTableId)\n            .fields.find((f) => f.id === r.endFieldId)?.name\n        }\")\\n\\tON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()}`,\n      );\n    }\n  });\n  return fks.join(\",\\n\");\n}\n"
  },
  {
    "path": "src/utils/exportSQL/sqlite.js",
    "content": "import { exportFieldComment, getInlineFK, parseDefault } from \"./shared\";\n\nimport { dbToTypes } from \"../../data/datatypes\";\n\nexport function toSqlite(diagram) {\n  return diagram.tables\n    .map((table) => {\n      const inlineFK = getInlineFK(table, diagram);\n      return `${\n        table.comment === \"\" ? \"\" : `/* ${table.comment} */\\n`\n      }CREATE TABLE IF NOT EXISTS \"${table.name}\" (\\n${table.fields\n        .map(\n          (field) =>\n            `${exportFieldComment(field.comment)}\\t\"${\n              field.name\n            }\" ${field.type}${field.notNull ? \" NOT NULL\" : \"\"}${\n              field.unique ? \" UNIQUE\" : \"\"\n            }${field.default !== \"\" ? ` DEFAULT ${parseDefault(field, diagram.database)}` : \"\"}${\n              field.check === \"\" ||\n              !dbToTypes[diagram.database][field.type].hasCheck\n                ? \"\"\n                : ` CHECK(${field.check})`\n            }`,\n        )\n        .join(\",\\n\")}${\n        table.fields.filter((f) => f.primary).length > 0\n          ? `,\\n\\tPRIMARY KEY(${table.fields\n              .filter((f) => f.primary)\n              .map((f) => `\"${f.name}\"`)\n              .join(\", \")})${inlineFK !== \"\" ? \",\\n\" : \"\"}`\n          : \"\"\n      }${inlineFK}\\n);\\n${table.indices\n        .map(\n          (i) =>\n            `\\nCREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX IF NOT EXISTS \"${\n              i.name\n            }\"\\nON \"${table.name}\" (${i.fields\n              .map((f) => `\"${f}\"`)\n              .join(\", \")});`,\n        )\n        .join(\"\\n\")}`;\n    })\n    .join(\"\\n\");\n}"
  },
  {
    "path": "src/utils/exportSavedData.js",
    "content": "import JSZip from \"jszip\";\nimport { db } from \"../data/db\";\nimport { saveAs } from \"file-saver\";\n\nconst zip = new JSZip();\n\nexport async function exportSavedData() {\n  const diagramsFolder = zip.folder(\"diagrams\");\n\n  await db.diagrams.each((diagram) => {\n    diagramsFolder.file(\n      `${diagram.name}(${diagram.id}).json`,\n      JSON.stringify(diagram, null, 2),\n    );\n    return true;\n  });\n\n  const templatesFolder = zip.folder(\"templates\");\n\n  await db.templates.where({ custom: 1 }).each((template) => {\n    templatesFolder.file(\n      `${template.title}(${template.id}).json`,\n      JSON.stringify(template, null, 2),\n    );\n    return true;\n  });\n\n  zip.generateAsync({ type: \"blob\" }).then(function (content) {\n    const date = new Date();\n    saveAs(\n      content,\n      `${date.getFullYear()}_${date.getMonth()}_${date.getDay()}_export.zip`,\n    );\n  });\n}\n"
  },
  {
    "path": "src/utils/fullscreen.js",
    "content": "export function enterFullscreen() {\n  const element = document.documentElement;\n  if (element.requestFullscreen) {\n    element.requestFullscreen();\n  } else if (element.mozRequestFullScreen) {\n    element.mozRequestFullScreen();\n  } else if (element.webkitRequestFullscreen) {\n    element.webkitRequestFullscreen();\n  } else if (element.msRequestFullscreen) {\n    element.msRequestFullscreen();\n  }\n}\n\nexport function exitFullscreen() {\n  if (document.exitFullscreen) {\n    document.exitFullscreen();\n  } else if (document.mozCancelFullScreen) {\n    document.mozCancelFullScreen();\n  } else if (document.webkitExitFullscreen) {\n    document.webkitExitFullscreen();\n  } else if (document.msExitFullscreen) {\n    document.msExitFullscreen();\n  }\n}\n"
  },
  {
    "path": "src/utils/importFrom/dbml.js",
    "content": "import { Parser } from \"@dbml/core\";\nimport { arrangeTables } from \"../arrangeTables\";\nimport { Cardinality, Constraint } from \"../../data/constants\";\nimport { nanoid } from \"nanoid\";\n\nconst parser = new Parser();\n\nexport function fromDBML(src) {\n  const ast = parser.parse(src, \"dbmlv2\");\n\n  const tables = [];\n  const enums = [];\n  const relationships = [];\n\n  for (const schema of ast.schemas) {\n    for (const table of schema.tables) {\n      let parsedTable = {};\n      parsedTable.id = nanoid();\n      parsedTable.name = table.name;\n      parsedTable.comment = table.note ?? \"\";\n      parsedTable.color = table.headerColor ?? \"#175e7a\";\n      parsedTable.fields = [];\n      parsedTable.indices = [];\n\n      for (const column of table.fields) {\n        const field = {};\n\n        field.id = nanoid();\n        field.name = column.name;\n        field.type = column.type.type_name.toUpperCase();\n        field.default = column.dbdefault?.value ?? \"\";\n        field.check = \"\";\n        field.primary = !!column.pk;\n        field.unique = !!column.pk;\n        field.notNull = !!column.not_null;\n        field.increment = !!column.increment;\n        field.comment = column.note ?? \"\";\n\n        parsedTable.fields.push(field);\n      }\n\n      for (const idx of table.indexes) {\n        const parsedIndex = {};\n\n        parsedIndex.id = idx.id - 1;\n        parsedIndex.fields = idx.columns.map((x) => x.value);\n        parsedIndex.name =\n          idx.name ?? `${parsedTable.name}_index_${parsedIndex.id}`;\n        parsedIndex.unique = !!idx.unique;\n\n        parsedTable.indices.push(parsedIndex);\n      }\n\n      tables.push(parsedTable);\n    }\n\n    for (const ref of schema.refs) {\n      const startTableName = ref.endpoints[0].tableName;\n      const endTableName = ref.endpoints[1].tableName;\n      const startFieldName = ref.endpoints[0].fieldNames[0];\n      const endFieldName = ref.endpoints[1].fieldNames[0];\n\n      const startTable = tables.find((t) => t.name === startTableName);\n      if (!startTable) continue;\n\n      const endTable = tables.find((t) => t.name === endTableName);\n      if (!endTable) continue;\n\n      const endField = endTable.fields.find((f) => f.name === endFieldName);\n      if (!endField) continue;\n\n      const startField = startTable.fields.find(\n        (f) => f.name === startFieldName,\n      );\n      if (!startField) continue;\n\n      const relationship = {};\n\n      relationship.name =\n        \"fk_\" + startTableName + \"_\" + startFieldName + \"_\" + endTableName;\n      relationship.startTableId = startTable.id;\n      relationship.endTableId = endTable.id;\n      relationship.endFieldId = endField.id;\n      relationship.startFieldId = startField.id;\n      relationship.id = nanoid();\n\n      relationship.updateConstraint = ref.onDelete\n        ? ref.onDelete[0].toUpperCase() + ref.onDelete.substring(1)\n        : Constraint.NONE;\n      relationship.deleteConstraint = ref.onUpdate\n        ? ref.onUpdate[0].toUpperCase() + ref.onUpdate.substring(1)\n        : Constraint.NONE;\n\n      const startRelation = ref.endpoints[0].relation;\n      const endRelation = ref.endpoints[1].relation;\n\n      if (startRelation === \"*\" && endRelation === \"1\") {\n        relationship.cardinality = Cardinality.MANY_TO_ONE;\n      }\n\n      if (startRelation === \"1\" && endRelation === \"*\") {\n        relationship.cardinality = Cardinality.ONE_TO_MANY;\n      }\n\n      if (startRelation === \"1\" && endRelation === \"1\") {\n        relationship.cardinality = Cardinality.ONE_TO_ONE;\n      }\n\n      relationships.push(relationship);\n    }\n\n    for (const schemaEnum of schema.enums) {\n      const parsedEnum = {};\n\n      parsedEnum.name = schemaEnum.name;\n      parsedEnum.values = schemaEnum.values.map((x) => x.name);\n\n      enums.push(parsedEnum);\n    }\n  }\n\n  const diagram = { tables, enums, relationships };\n\n  arrangeTables(diagram);\n\n  return diagram;\n}\n"
  },
  {
    "path": "src/utils/importSQL/index.js",
    "content": "import { DB } from \"../../data/constants\";\nimport { arrangeTables } from \"../arrangeTables\";\nimport { fromMariaDB } from \"./mariadb\";\nimport { fromMSSQL } from \"./mssql\";\nimport { fromMySQL } from \"./mysql\";\nimport { fromOracleSQL } from \"./oraclesql\";\nimport { fromPostgres } from \"./postgres\";\nimport { fromSQLite } from \"./sqlite\";\n\nexport function importSQL(ast, toDb = DB.MYSQL, diagramDb = DB.GENERIC) {\n  let diagram;\n  switch (toDb) {\n    case DB.SQLITE:\n      diagram = fromSQLite(ast, diagramDb);\n      break;\n    case DB.MYSQL:\n      diagram = fromMySQL(ast, diagramDb);\n      break;\n    case DB.POSTGRES:\n      diagram = fromPostgres(ast, diagramDb);\n      break;\n    case DB.MARIADB:\n      diagram = fromMariaDB(ast, diagramDb);\n      break;\n    case DB.MSSQL:\n      diagram = fromMSSQL(ast, diagramDb);\n      break;\n    case DB.ORACLESQL:\n      diagram = fromOracleSQL(ast, diagramDb);\n      break;\n    default:\n      diagram = { tables: [], relationships: [] };\n      break;\n  }\n\n  arrangeTables(diagram);\n\n  return diagram;\n}\n"
  },
  {
    "path": "src/utils/importSQL/mariadb.js",
    "content": "import { nanoid } from \"nanoid\";\nimport { Cardinality, DB } from \"../../data/constants\";\nimport { dbToTypes } from \"../../data/datatypes\";\nimport { buildSQLFromAST } from \"./shared\";\n\nconst affinity = {\n  [DB.MARIADB]: new Proxy(\n    { INT: \"INTEGER\" },\n    { get: (target, prop) => (prop in target ? target[prop] : \"BLOB\") },\n  ),\n  [DB.GENERIC]: new Proxy(\n    {\n      INT: \"INTEGER\",\n      TINYINT: \"SMALLINT\",\n      MEDIUMINT: \"INTEGER\",\n      BIT: \"BOOLEAN\",\n      YEAR: \"INTEGER\",\n    },\n    { get: (target, prop) => (prop in target ? target[prop] : \"BLOB\") },\n  ),\n};\n\nexport function fromMariaDB(ast, diagramDb = DB.GENERIC) {\n  const tables = [];\n  const relationships = [];\n\n  const parseSingleStatement = (e) => {\n    if (e.type === \"create\") {\n      if (e.keyword === \"table\") {\n        const table = {};\n        table.name = e.table[0].table;\n        table.comment = \"\";\n        table.color = \"#175e7a\";\n        table.fields = [];\n        table.indices = [];\n        table.id = nanoid();\n        e.create_definitions.forEach((d) => {\n          if (d.resource === \"column\") {\n            const field = {};\n            field.id = nanoid();\n            field.name = d.column.column;\n\n            let type = d.definition.dataType;\n            if (!dbToTypes[diagramDb][type]) {\n              type = affinity[diagramDb][type];\n            }\n            field.type = type;\n\n            if (d.definition.expr && d.definition.expr.type === \"expr_list\") {\n              field.values = d.definition.expr.value.map((v) => v.value);\n            }\n            field.comment = d.comment ? d.comment.value.value : \"\";\n            field.unique = false;\n            if (d.unique) field.unique = true;\n            field.increment = false;\n            if (d.auto_increment) field.increment = true;\n            field.notNull = false;\n            if (d.nullable) field.notNull = true;\n            field.primary = false;\n            if (d.primary_key) field.primary = true;\n            field.default = \"\";\n            if (d.default_val) {\n              let defaultValue = \"\";\n              if (d.default_val.value.type === \"function\") {\n                defaultValue = d.default_val.value.name.name[0].value;\n                if (d.default_val.value.args) {\n                  defaultValue +=\n                    \"(\" +\n                    d.default_val.value.args.value\n                      .map((v) => {\n                        if (\n                          v.type === \"single_quote_string\" ||\n                          v.type === \"double_quote_string\"\n                        )\n                          return \"'\" + v.value + \"'\";\n                        return v.value;\n                      })\n                      .join(\", \") +\n                    \")\";\n                }\n              } else if (d.default_val.value.type === \"null\") {\n                defaultValue = \"NULL\";\n              } else {\n                defaultValue = d.default_val.value.value.toString();\n              }\n              field.default = defaultValue;\n            }\n            if (d.definition[\"length\"]) {\n              if (d.definition.scale) {\n                field.size = d.definition[\"length\"] + \",\" + d.definition.scale;\n              } else {\n                field.size = d.definition[\"length\"];\n              }\n            }\n            field.check = \"\";\n            if (d.check) {\n              field.check = buildSQLFromAST(d.check.definition[0], DB.MARIADB);\n            }\n\n            table.fields.push(field);\n          } else if (d.resource === \"constraint\") {\n            if (d.constraint_type === \"primary key\") {\n              d.definition.forEach((c) => {\n                table.fields.forEach((f) => {\n                  if (f.name === c.column && !f.primary) {\n                    f.primary = true;\n                  }\n                });\n              });\n            } else if (d.constraint_type.toLowerCase() === \"foreign key\") {\n              const relationship = {};\n              const startTableId = table.id;\n              const startTableName = e.table[0].table;\n              const startFieldName = d.definition[0].column;\n              const endTableName = d.reference_definition.table[0].table;\n              const endFieldName = d.reference_definition.definition[0].column;\n\n              const endTable = tables.find((t) => t.name === endTableName);\n              if (!endTable) return;\n\n              const endField = endTable.fields.find(\n                (f) => f.name === endFieldName,\n              );\n              if (!endField) return;\n\n              const startField = table.fields.find(\n                (f) => f.name === startFieldName,\n              );\n              if (!startField) return;\n\n              relationship.name = `fk_${startTableName}_${startFieldName}_${endTableName}`;\n              relationship.startTableId = startTableId;\n              relationship.endTableId = endTable.id;\n              relationship.endFieldId = endField.id;\n              relationship.startFieldId = startField.id;\n              relationship.id = nanoid()\n              let updateConstraint = \"No action\";\n              let deleteConstraint = \"No action\";\n              d.reference_definition.on_action.forEach((c) => {\n                if (c.type === \"on update\") {\n                  updateConstraint = c.value.value;\n                  updateConstraint =\n                    updateConstraint[0].toUpperCase() +\n                    updateConstraint.substring(1);\n                } else if (c.type === \"on delete\") {\n                  deleteConstraint = c.value.value;\n                  deleteConstraint =\n                    deleteConstraint[0].toUpperCase() +\n                    deleteConstraint.substring(1);\n                }\n              });\n\n              relationship.updateConstraint = updateConstraint;\n              relationship.deleteConstraint = deleteConstraint;\n\n              if (startField.unique) {\n                relationship.cardinality = Cardinality.ONE_TO_ONE;\n              } else {\n                relationship.cardinality = Cardinality.MANY_TO_ONE;\n              }\n\n              relationships.push(relationship);\n            }\n          }\n        });\n\n        e.table_options?.forEach((opt) => {\n          if (opt.keyword === \"comment\") {\n            table.comment = opt.value.replace(/^[\"']|[\"']$/g, \"\");\n          }\n        });\n\n        tables.push(table);\n      } else if (e.keyword === \"index\") {\n        const index = {\n          name: e.index,\n          unique: e.index_type === \"unique\",\n          fields: e.index_columns.map((f) => f.column),\n        };\n\n        const table = tables.find((t) => t.name === e.table.table);\n\n        if (table) {\n          table.indices.push(index);\n          table.indices.forEach((i, j) => {\n            i.id = j;\n          });\n        }\n      }\n    } else if (e.type === \"alter\") {\n      e.expr.forEach((expr) => {\n        if (\n          expr.action === \"add\" &&\n          expr.create_definitions.constraint_type.toLowerCase() ===\n            \"foreign key\"\n        ) {\n          const relationship = {};\n          const startTableName = e.table[0].table;\n          const startFieldName = expr.create_definitions.definition[0].column;\n          const endTableName =\n            expr.create_definitions.reference_definition.table[0].table;\n          const endFieldName =\n            expr.create_definitions.reference_definition.definition[0].column;\n          let updateConstraint = \"No action\";\n          let deleteConstraint = \"No action\";\n          expr.create_definitions.reference_definition.on_action.forEach(\n            (c) => {\n              if (c.type === \"on update\") {\n                updateConstraint = c.value.value;\n                updateConstraint =\n                  updateConstraint[0].toUpperCase() +\n                  updateConstraint.substring(1);\n              } else if (c.type === \"on delete\") {\n                deleteConstraint = c.value.value;\n                deleteConstraint =\n                  deleteConstraint[0].toUpperCase() +\n                  deleteConstraint.substring(1);\n              }\n            },\n          );\n\n          const startTable = tables.find((t) => t.name === startTableName);\n          if (!startTable) return;\n\n          const endTable = tables.find((t) => t.name === endTableName);\n          if (!endTable) return;\n\n          const endField = endTable.fields.find((f) => f.name === endFieldName);\n          if (!endField) return;\n\n          const startField = startTable.fields.find(\n            (f) => f.name === startFieldName,\n          );\n          if (!startField) return;\n\n          relationship.name =\n            \"fk_\" + startTableName + \"_\" + startFieldName + \"_\" + endTableName;\n          relationship.startTableId = startTable.id;\n          relationship.startFieldId = startField.id;\n          relationship.endTableId = endTable.id;\n          relationship.endFieldId = endField.id;\n          relationship.updateConstraint = updateConstraint;\n          relationship.deleteConstraint = deleteConstraint;\n          relationship.id = nanoid();\n\n          if (startField.unique) {\n            relationship.cardinality = Cardinality.ONE_TO_ONE;\n          } else {\n            relationship.cardinality = Cardinality.MANY_TO_ONE;\n          }\n\n          relationships.push(relationship);\n        }\n      });\n    }\n  };\n\n  if (Array.isArray(ast)) {\n    ast.forEach((e) => parseSingleStatement(e));\n  } else {\n    parseSingleStatement(ast);\n  }\n\n  return { tables, relationships };\n}\n"
  },
  {
    "path": "src/utils/importSQL/mssql.js",
    "content": "import { nanoid } from \"nanoid\";\nimport { Cardinality, DB } from \"../../data/constants\";\nimport { dbToTypes } from \"../../data/datatypes\";\nimport { buildSQLFromAST } from \"./shared\";\n\nconst affinity = {\n  [DB.MSSQL]: new Proxy(\n    { INT: \"INTEGER\" },\n    { get: (target, prop) => (prop in target ? target[prop] : \"TEXT\") },\n  ),\n  [DB.GENERIC]: new Proxy(\n    {\n      INTEGER: \"INT\",\n      TINYINT: \"SMALLINT\",\n      MEDIUMINT: \"INTEGER\",\n      BIT: \"BOOLEAN\",\n      DATETIME2: \"DATETIME\",\n      MONEY: \"NUMERIC\",\n      SMALLMONEY: \"NUMERIC\",\n      NCHAR: \"CHAR\",\n      NVARCHAR: \"VARCHAR\",\n      NTEXT: \"TEXT\",\n      IMAGE: \"BLOB\",\n      XML: \"BLOB\",\n      DATETIMEOFFSET: \"TEXT\",\n      SQL_VARIANT: \"TEXT\",\n      UNIQUEIDENTIFIER: \"UUID\",\n      SMALLDATETIME: \"DATETIME\",\n      CURSOR: \"BLOB\",\n    },\n    { get: (target, prop) => (prop in target ? target[prop] : \"TEXT\") },\n  ),\n};\n\nexport function fromMSSQL(ast, diagramDb = DB.GENERIC) {\n  const tables = [];\n  const relationships = [];\n\n  const parseSingleStatement = (e) => {\n    if (e.type === \"create\") {\n      if (e.keyword === \"table\") {\n        const table = {};\n        table.name = e.table[0].table;\n        table.comment = \"\";\n        table.color = \"#175e7a\";\n        table.fields = [];\n        table.indices = [];\n        table.id = nanoid();\n        e.create_definitions.forEach((d) => {\n          if (d.resource === \"column\") {\n            const field = {};\n            field.id = nanoid();\n            field.name = d.column.column;\n\n            let type = d.definition.dataType;\n            if (!dbToTypes[diagramDb][type]) {\n              type = affinity[diagramDb][type];\n            }\n            field.type = type;\n\n            if (d.definition.expr && d.definition.expr.type === \"expr_list\") {\n              field.values = d.definition.expr.value.map((v) => v.value);\n            }\n            field.comment = d.comment ? d.comment.value.value : \"\";\n            field.unique = false;\n            if (d.unique) field.unique = true;\n            field.increment = false;\n            if (d.auto_increment) field.increment = true;\n            field.notNull = false;\n            if (d.nullable) field.notNull = true;\n            field.primary = false;\n            if (d.primary_key) field.primary = true;\n            field.default = \"\";\n            if (d.default_val) {\n              let defaultValue = \"\";\n              if (d.default_val.value.type === \"function\") {\n                defaultValue = d.default_val.value.name.name[0].value;\n                if (d.default_val.value.args) {\n                  defaultValue +=\n                    \"(\" +\n                    d.default_val.value.args.value\n                      .map((v) => {\n                        if (\n                          v.type === \"single_quote_string\" ||\n                          v.type === \"double_quote_string\"\n                        )\n                          return \"'\" + v.value + \"'\";\n                        return v.value;\n                      })\n                      .join(\", \") +\n                    \")\";\n                }\n              } else if (d.default_val.value.type === \"null\") {\n                defaultValue = \"NULL\";\n              } else {\n                defaultValue = d.default_val.value.value.toString();\n              }\n              field.default = defaultValue;\n            }\n            if (d.definition[\"length\"]) {\n              if (d.definition.scale) {\n                field.size = d.definition[\"length\"] + \",\" + d.definition.scale;\n              } else {\n                field.size = d.definition[\"length\"];\n              }\n            }\n            field.check = \"\";\n            if (d.check) {\n              field.check = buildSQLFromAST(d.check.definition[0], DB.MSSQL);\n            }\n\n            table.fields.push(field);\n          } else if (d.resource === \"constraint\") {\n            if (d.constraint_type === \"primary key\") {\n              d.definition.forEach((c) => {\n                table.fields.forEach((f) => {\n                  if (f.name === c.column && !f.primary) {\n                    f.primary = true;\n                  }\n                });\n              });\n            } else if (d.constraint_type.toLowerCase() === \"foreign key\") {\n              const relationship = {};\n              const startTableId = table.id;\n              const startTableName = e.table[0].table;\n              const startFieldName = d.definition[0].column;\n              const endTableName = d.reference_definition.table[0].table;\n              const endFieldName = d.reference_definition.definition[0].column;\n\n              const endTable = tables.find((t) => t.name === endTableName);\n              if (!endTable) return;\n\n              const endField = endTable.fields.find(\n                (f) => f.name === endFieldName,\n              );\n              if (!endField) return;\n\n              const startField = table.fields.find(\n                (f) => f.name === startFieldName,\n              );\n              if (!startField) return;\n\n              relationship.name = `fk_${startTableName}_${startFieldName}_${endTableName}`;\n              relationship.startTableId = startTableId;\n              relationship.endTableId = endTable.id;\n              relationship.endFieldId = endField.id;\n              relationship.startFieldId = startField.id;\n              relationship.id = nanoid();\n\n              let updateConstraint = \"No action\";\n              let deleteConstraint = \"No action\";\n              d.reference_definition.on_action.forEach((c) => {\n                if (c.type === \"on update\") {\n                  updateConstraint = c.value.value;\n                  updateConstraint =\n                    updateConstraint[0].toUpperCase() +\n                    updateConstraint.substring(1);\n                } else if (c.type === \"on delete\") {\n                  deleteConstraint = c.value.value;\n                  deleteConstraint =\n                    deleteConstraint[0].toUpperCase() +\n                    deleteConstraint.substring(1);\n                }\n              });\n\n              relationship.updateConstraint = updateConstraint;\n              relationship.deleteConstraint = deleteConstraint;\n\n              if (startField.unique) {\n                relationship.cardinality = Cardinality.ONE_TO_ONE;\n              } else {\n                relationship.cardinality = Cardinality.MANY_TO_ONE;\n              }\n\n              relationships.push(relationship);\n            }\n          }\n        });\n        tables.push(table);\n      } else if (e.keyword === \"index\") {\n        const index = {\n          name: e.index,\n          unique: e.index_type === \"unique\",\n          fields: e.index_columns.map((f) => f.column),\n        };\n\n        const table = tables.find((t) => t.name === e.table.table);\n\n        if (table) {\n          table.indices.push(index);\n          table.indices.forEach((i, j) => {\n            i.id = j;\n          });\n        }\n      }\n    } else if (e.type === \"alter\") {\n      e.expr.forEach((expr) => {\n        if (\n          expr.action === \"add\" &&\n          expr.create_definitions.constraint_type.toLowerCase() ===\n            \"foreign key\"\n        ) {\n          const relationship = {};\n          const startTableName = e.table[0].table;\n          const startFieldName = expr.create_definitions.definition[0].column;\n          const endTableName =\n            expr.create_definitions.reference_definition.table[0].table;\n          const endFieldName =\n            expr.create_definitions.reference_definition.definition[0].column;\n          let updateConstraint = \"No action\";\n          let deleteConstraint = \"No action\";\n          expr.create_definitions.reference_definition.on_action.forEach(\n            (c) => {\n              if (c.type === \"on update\") {\n                updateConstraint = c.value.value;\n                updateConstraint =\n                  updateConstraint[0].toUpperCase() +\n                  updateConstraint.substring(1);\n              } else if (c.type === \"on delete\") {\n                deleteConstraint = c.value.value;\n                deleteConstraint =\n                  deleteConstraint[0].toUpperCase() +\n                  deleteConstraint.substring(1);\n              }\n            },\n          );\n\n          const startTable = tables.find((t) => t.name === startTableName);\n          if (!startTable) return;\n\n          const endTable = tables.find((t) => t.name === endTableName);\n          if (!endTable) return;\n\n          const endField = endTable.fields.find((f) => f.name === endFieldName);\n          if (!endField) return;\n\n          const startField = startTable.fields.find(\n            (f) => f.name === startFieldName,\n          );\n          if (!startField) return;\n\n          relationship.name = `fk_${startTableName}_${startFieldName}_${endTableName}`;\n          relationship.startTableId = startTable.id;\n          relationship.startFieldId = startField.id;\n          relationship.endTableId = endTable.id;\n          relationship.endFieldId = endField.id;\n          relationship.updateConstraint = updateConstraint;\n          relationship.deleteConstraint = deleteConstraint;\n          relationship.id = nanoid();\n\n          if (startField.unique) {\n            relationship.cardinality = Cardinality.ONE_TO_ONE;\n          } else {\n            relationship.cardinality = Cardinality.MANY_TO_ONE;\n          }\n\n          relationships.push(relationship);\n        }\n      });\n    }\n  };\n\n  if (ast.go_next) {\n    let x = { ...ast };\n    let done = false;\n    while (!done) {\n      parseSingleStatement(x.ast);\n      done = Array.isArray(x.go_next) && x.go_next.length === 0;\n      x = { ...x.go_next };\n    }\n  } else if (Array.isArray(ast)) {\n    ast.forEach((e) => {\n      parseSingleStatement(e);\n    });\n  } else if (typeof ast === \"object\") {\n    parseSingleStatement(ast);\n  }\n\n  return { tables, relationships };\n}\n"
  },
  {
    "path": "src/utils/importSQL/mysql.js",
    "content": "import { nanoid } from \"nanoid\";\nimport { Cardinality, DB } from \"../../data/constants\";\nimport { dbToTypes } from \"../../data/datatypes\";\nimport { buildSQLFromAST } from \"./shared\";\n\nconst affinity = {\n  [DB.MYSQL]: new Proxy(\n    { INT: \"INTEGER\" },\n    { get: (target, prop) => (prop in target ? target[prop] : \"BLOB\") },\n  ),\n  [DB.GENERIC]: new Proxy(\n    {\n      INTEGER: \"INT\",\n      TINYINT: \"SMALLINT\",\n      MEDIUMINT: \"INTEGER\",\n      BIT: \"BOOLEAN\",\n      YEAR: \"INTEGER\",\n    },\n    { get: (target, prop) => (prop in target ? target[prop] : \"BLOB\") },\n  ),\n};\n\nexport function fromMySQL(ast, diagramDb = DB.GENERIC) {\n  const tables = [];\n  const relationships = [];\n\n  const parseSingleStatement = (e) => {\n    if (e.type === \"create\") {\n      if (e.keyword === \"table\") {\n        const table = {};\n        table.name = e.table[0].table;\n        table.comment = \"\";\n        table.color = \"#175e7a\";\n        table.fields = [];\n        table.indices = [];\n        table.id = nanoid();\n        e.create_definitions.forEach((d) => {\n          if (d.resource === \"column\") {\n            const field = {};\n            field.id = nanoid();\n            field.name = d.column.column;\n\n            let type = d.definition.dataType;\n            if (!dbToTypes[diagramDb][type]) {\n              type = affinity[diagramDb][type];\n            }\n            field.type = type;\n\n            if (d.definition.expr && d.definition.expr.type === \"expr_list\") {\n              field.values = d.definition.expr.value.map((v) => v.value);\n            }\n            field.comment = d.comment ? d.comment.value.value : \"\";\n            field.unique = false;\n            if (d.unique) field.unique = true;\n            field.increment = false;\n            if (d.auto_increment) field.increment = true;\n            field.notNull = false;\n            if (d.nullable) field.notNull = true;\n            field.primary = false;\n            if (d.primary_key) field.primary = true;\n            field.default = \"\";\n            if (d.default_val) {\n              let defaultValue = \"\";\n              if (d.default_val.value.type === \"function\") {\n                defaultValue = d.default_val.value.name.name[0].value;\n                if (d.default_val.value.args) {\n                  defaultValue +=\n                    \"(\" +\n                    d.default_val.value.args.value\n                      .map((v) => {\n                        if (\n                          v.type === \"single_quote_string\" ||\n                          v.type === \"double_quote_string\"\n                        )\n                          return \"'\" + v.value + \"'\";\n                        return v.value;\n                      })\n                      .join(\", \") +\n                    \")\";\n                }\n              } else if (d.default_val.value.type === \"null\") {\n                defaultValue = \"NULL\";\n              } else {\n                defaultValue = d.default_val.value.value.toString();\n              }\n              field.default = defaultValue;\n            }\n            if (d.definition[\"length\"]) {\n              if (d.definition.scale) {\n                field.size = d.definition[\"length\"] + \",\" + d.definition.scale;\n              } else {\n                field.size = d.definition[\"length\"];\n              }\n            }\n            field.check = \"\";\n            if (d.check) {\n              field.check = buildSQLFromAST(d.check.definition[0], DB.MYSQL);\n            }\n\n            table.fields.push(field);\n          } else if (d.resource === \"constraint\") {\n            if (d.constraint_type === \"primary key\") {\n              d.definition.forEach((c) => {\n                table.fields.forEach((f) => {\n                  if (f.name === c.column && !f.primary) {\n                    f.primary = true;\n                  }\n                });\n              });\n            } else if (d.constraint_type.toLowerCase() === \"foreign key\") {\n              const relationship = {};\n              const startTableName = e.table[0].table;\n              const startFieldName = d.definition[0].column;\n              const endTableName = d.reference_definition.table[0].table;\n              const endFieldName = d.reference_definition.definition[0].column;\n\n              const endTable = tables.find((t) => t.name === endTableName);\n              if (!endTable) return;\n\n              const endField = endTable.fields.find(\n                (f) => f.name === endFieldName,\n              );\n              if (!endField) return;\n\n              const startField = table.fields.find(\n                (f) => f.name === startFieldName,\n              );\n              if (!startField) return;\n\n              relationship.name = `fk_${startTableName}_${startFieldName}_${endTableName}`;\n              relationship.startTableId = table.id;\n              relationship.endTableId = endTable.id;\n              relationship.endFieldId = endField.id;\n              relationship.startFieldId = startField.id;\n              relationship.id = nanoid();\n\n              let updateConstraint = \"No action\";\n              let deleteConstraint = \"No action\";\n              d.reference_definition.on_action.forEach((c) => {\n                if (c.type === \"on update\") {\n                  updateConstraint = c.value.value;\n                  updateConstraint =\n                    updateConstraint[0].toUpperCase() +\n                    updateConstraint.substring(1);\n                } else if (c.type === \"on delete\") {\n                  deleteConstraint = c.value.value;\n                  deleteConstraint =\n                    deleteConstraint[0].toUpperCase() +\n                    deleteConstraint.substring(1);\n                }\n              });\n\n              relationship.updateConstraint = updateConstraint;\n              relationship.deleteConstraint = deleteConstraint;\n\n              if (startField.unique) {\n                relationship.cardinality = Cardinality.ONE_TO_ONE;\n              } else {\n                relationship.cardinality = Cardinality.MANY_TO_ONE;\n              }\n\n              relationships.push(relationship);\n            }\n          }\n        });\n\n        e.table_options?.forEach((opt) => {\n          if (opt.keyword === \"comment\") {\n            table.comment = opt.value.replace(/^[\"']|[\"']$/g, \"\");\n          }\n        });\n\n        tables.push(table);\n      } else if (e.keyword === \"index\") {\n        const index = {\n          name: e.index,\n          unique: e.index_type === \"unique\",\n          fields: e.index_columns.map((f) => f.column),\n        };\n\n        const table = tables.find((t) => t.name === e.table.table);\n\n        if (table) {\n          table.indices.push(index);\n          table.indices.forEach((i, j) => {\n            i.id = j;\n          });\n        }\n      }\n    } else if (e.type === \"alter\") {\n      e.expr.forEach((expr) => {\n        if (\n          expr.action === \"add\" &&\n          expr.create_definitions.constraint_type.toLowerCase() ===\n            \"foreign key\"\n        ) {\n          const relationship = {};\n          const startTableName = e.table[0].table;\n          const startFieldName = expr.create_definitions.definition[0].column;\n          const endTableName =\n            expr.create_definitions.reference_definition.table[0].table;\n          const endFieldName =\n            expr.create_definitions.reference_definition.definition[0].column;\n          let updateConstraint = \"No action\";\n          let deleteConstraint = \"No action\";\n          expr.create_definitions.reference_definition.on_action.forEach(\n            (c) => {\n              if (c.type === \"on update\") {\n                updateConstraint = c.value.value;\n                updateConstraint =\n                  updateConstraint[0].toUpperCase() +\n                  updateConstraint.substring(1);\n              } else if (c.type === \"on delete\") {\n                deleteConstraint = c.value.value;\n                deleteConstraint =\n                  deleteConstraint[0].toUpperCase() +\n                  deleteConstraint.substring(1);\n              }\n            },\n          );\n\n          const startTable = tables.find((t) => t.name === startTableName);\n          if (!startTable) return;\n\n          const endTable = tables.find((t) => t.name === endTableName);\n          if (!endTable) return;\n\n          const endField = endTable.fields.find((f) => f.name === endFieldName);\n          if (!endField) return;\n\n          const startField = startTable.fields.find(\n            (f) => f.name === startFieldName,\n          );\n          if (!startField) return;\n\n          relationship.name = `fk_${startTableName}_${startFieldName}_${endTableName}`;\n          relationship.startTableId = startTable.id;\n          relationship.startFieldId = startField.id;\n          relationship.endTableId = endTable.id;\n          relationship.endFieldId = endField.id;\n          relationship.updateConstraint = updateConstraint;\n          relationship.deleteConstraint = deleteConstraint;\n          relationship.id = nanoid();\n\n          if (startField.unique) {\n            relationship.cardinality = Cardinality.ONE_TO_ONE;\n          } else {\n            relationship.cardinality = Cardinality.MANY_TO_ONE;\n          }\n\n          relationships.push(relationship);\n        }\n      });\n    }\n  };\n\n  if (Array.isArray(ast)) {\n    ast.forEach((e) => parseSingleStatement(e));\n  } else {\n    parseSingleStatement(ast);\n  }\n\n  return { tables, relationships };\n}\n"
  },
  {
    "path": "src/utils/importSQL/oraclesql.js",
    "content": "import { nanoid } from \"nanoid\";\nimport { Cardinality, Constraint, DB } from \"../../data/constants\";\nimport { dbToTypes } from \"../../data/datatypes\";\n\nconst affinity = {\n  [DB.ORACLESQL]: new Proxy(\n    {\n      INT: \"INTEGER\",\n      NUMERIC: \"NUMBER\",\n      DECIMAL: \"NUMBER\",\n      CHARACTER: \"CHAR\",\n    },\n    { get: (target, prop) => (prop in target ? target[prop] : \"BLOB\") },\n  ),\n  [DB.GENERIC]: new Proxy(\n    {\n      INTEGER: \"INT\",\n      MEDIUMINT: \"INTEGER\",\n    },\n    { get: (target, prop) => (prop in target ? target[prop] : \"BLOB\") },\n  ),\n};\n\nexport function fromOracleSQL(ast, diagramDb = DB.GENERIC) {\n  const tables = [];\n  const relationships = [];\n  const enums = [];\n\n  const parseSingleStatement = (e) => {\n    if (e.operation === \"create\") {\n      if (e.object === \"table\") {\n        const table = {};\n        table.name = e.name.name;\n        table.comment = \"\";\n        table.color = \"#175e7a\";\n        table.fields = [];\n        table.indices = [];\n        table.id = nanoid();\n        e.table.relational_properties.forEach((d) => {\n          if (d.resource === \"column\") {\n            const field = {};\n            field.id = nanoid();\n            field.name = d.name;\n\n            let type = d.type.type.toUpperCase();\n            if (!dbToTypes[diagramDb][type]) {\n              type = affinity[diagramDb][type];\n            }\n            field.type = type;\n\n            if (d.type.scale && d.type.precision) {\n              field.size = d.type.precision + \",\" + d.type.scale;\n            } else if (d.type.size || d.type.precision) {\n              field.size = d.type.size || d.type.precision;\n            }\n\n            field.comment = \"\";\n            field.check = \"\";\n            field.default = \"\";\n            field.unique = false;\n            field.increment = false;\n            field.notNull = false;\n            field.primary = false;\n\n            for (const c of d.constraints) {\n              if (c.constraint.primary_key === \"primary key\")\n                field.primary = true;\n              if (c.constraint.not_null === \"not null\") field.notNull = true;\n              if (c.constraint.unique === \"unique\") field.unique = true;\n            }\n\n            if (d.identity) {\n              field.increment = true;\n            }\n\n            // TODO: reconstruct default when implemented in parser\n            if (d.default) {\n              field.default = JSON.stringify(d.default.expr);\n            }\n\n            table.fields.push(field);\n          } else if (d.resource === \"constraint\") {\n            const relationship = {};\n            const startFieldName = d.constraint.columns[0];\n            const endFieldName = d.constraint.reference.columns[0];\n            const endTableName = d.constraint.reference.object.name;\n\n            const endTable = tables.find((t) => t.name === endTableName);\n            if (!endTable) return;\n\n            const endField = endTable.fields.find(\n              (f) => f.name === endFieldName,\n            );\n            if (!endField) return;\n\n            const startField = table.fields.find(\n              (f) => f.name === startFieldName,\n            );\n            if (!startField) return;\n\n            relationship.id = nanoid();\n            relationship.startTableId = table.id;\n            relationship.startFieldId = startField.id;\n            relationship.endTableId = endTable.id;\n            relationship.endFieldId = endField.id;\n            relationship.updateConstraint = Constraint.NONE;\n            relationship.name =\n              d.name && Boolean(d.name.trim())\n                ? d.name\n                : `fk_${table.name}_${startFieldName}_${endTableName}`;\n            relationship.deleteConstraint =\n              d.constraint.reference.on_delete &&\n              Boolean(d.constraint.reference.on_delete.trim())\n                ? d.constraint.reference.on_delete[0].toUpperCase() +\n                  d.constraint.reference.on_delete.substring(1)\n                : Constraint.NONE;\n\n            if (startField.unique) {\n              relationship.cardinality = Cardinality.ONE_TO_ONE;\n            } else {\n              relationship.cardinality = Cardinality.MANY_TO_ONE;\n            }\n\n            relationships.push(relationship);\n          }\n        });\n        tables.push(table);\n      }\n    }\n  };\n\n  ast.forEach((e) => parseSingleStatement(e));\n\n  return { tables, relationships, enums };\n}\n"
  },
  {
    "path": "src/utils/importSQL/postgres.js",
    "content": "import { nanoid } from \"nanoid\";\nimport { Cardinality, Constraint, DB } from \"../../data/constants\";\nimport { dbToTypes } from \"../../data/datatypes\";\nimport { buildSQLFromAST } from \"./shared\";\n\nconst affinity = {\n  [DB.POSTGRES]: new Proxy(\n    { INT: \"INTEGER\" },\n    { get: (target, prop) => (prop in target ? target[prop] : \"BLOB\") },\n  ),\n  [DB.GENERIC]: new Proxy(\n    {\n      INTEGER: \"INT\",\n      MEDIUMINT: \"INTEGER\",\n      BIT: \"BOOLEAN\",\n      \"CHARACTER VARYING\": \"VARCHAR\",\n    },\n    { get: (target, prop) => (prop in target ? target[prop] : \"BLOB\") },\n  ),\n};\n\nexport function fromPostgres(ast, diagramDb = DB.GENERIC) {\n  const tables = [];\n  const relationships = [];\n  const types = [];\n  const enums = [];\n\n  const parseSingleStatement = (e) => {\n    if (e.type === \"create\") {\n      if (e.keyword === \"table\") {\n        const table = {};\n        table.name = e.table[0].table;\n        table.comment = \"\";\n        table.color = \"#175e7a\";\n        table.fields = [];\n        table.indices = [];\n        table.id = nanoid();\n        e.create_definitions.forEach((d) => {\n          const field = {};\n          if (d.resource === \"column\") {\n            field.id = nanoid();\n            field.name = d.column.column.expr.value;\n\n            let type = types.find((t) =>\n              new RegExp(`^(${t.name}|\"${t.name}\")$`).test(\n                d.definition.dataType,\n              ),\n            )?.name;\n            type ??= enums.find((t) =>\n              new RegExp(`^(${t.name}|\"${t.name}\")$`).test(\n                d.definition.dataType,\n              ),\n            )?.name;\n\n            type ??=\n              dbToTypes[diagramDb][d.definition.dataType.toUpperCase()].type;\n            type ??= affinity[diagramDb][d.definition.dataType.toUpperCase()];\n\n            field.type = type;\n\n            if (d.definition.expr && d.definition.expr.type === \"expr_list\") {\n              field.values = d.definition.expr.value.map((v) => v.value);\n            }\n            field.comment = d.comment ? d.comment.value.value : \"\";\n            field.unique = false;\n            if (d.unique) field.unique = true;\n            field.increment = false;\n            if (d.auto_increment) field.increment = true;\n            field.notNull = false;\n            if (d.nullable) field.notNull = true;\n            field.primary = false;\n            if (d.primary_key) field.primary = true;\n            field.default = \"\";\n            if (d.default_val) {\n              let defaultValue = \"\";\n              if (d.default_val.value.type === \"function\") {\n                defaultValue = d.default_val.value.name.name[0].value;\n                if (d.default_val.value.args) {\n                  defaultValue +=\n                    \"(\" +\n                    d.default_val.value.args.value\n                      .map((v) => {\n                        if (\n                          v.type === \"single_quote_string\" ||\n                          v.type === \"double_quote_string\"\n                        )\n                          return \"'\" + v.value + \"'\";\n                        return v.value;\n                      })\n                      .join(\", \") +\n                    \")\";\n                }\n              } else if (d.default_val.value.type === \"null\") {\n                defaultValue = \"NULL\";\n              } else if (d.default_val.value.type === \"cast\") {\n                defaultValue = d.default_val.value.expr.value;\n              } else if (d.default_val.value.type === \"array\") {\n                defaultValue = `ARRAY[${d.default_val.value.expr_list.value\n                  .map((v) => v.value ?? v.expr.value)\n                  .join(\", \")}]`;\n              } else {\n                defaultValue = d.default_val.value.value.toString();\n              }\n              field.default = defaultValue;\n            }\n            if (d.definition[\"length\"]) {\n              if (d.definition.scale) {\n                field.size = d.definition[\"length\"] + \",\" + d.definition.scale;\n              } else {\n                field.size = d.definition[\"length\"];\n              }\n            }\n            field.check = \"\";\n            if (d.check) {\n              field.check = buildSQLFromAST(d.check.definition[0], DB.POSTGRES);\n            }\n\n            table.fields.push(field);\n          } else if (d.resource === \"constraint\") {\n            if (d.constraint_type === \"primary key\") {\n              d.definition.forEach((c) => {\n                table.fields.forEach((f) => {\n                  if (f.name === c.column.expr.value && !f.primary) {\n                    f.primary = true;\n                  }\n                });\n              });\n            } else if (d.constraint_type.toLowerCase() === \"foreign key\") {\n              const relationship = {};\n              const startTableId = table.id;\n              const startTableName = e.table[0].table;\n              const startFieldName = d.definition[0].column.expr.value;\n              const endTableName = d.reference_definition.table[0].table;\n              const endFieldName =\n                d.reference_definition.definition[0].column.expr.value;\n\n              const endTable = tables.find((t) => t.name === endTableName);\n              if (!endTable) return;\n\n              const endField = endTable.fields.find(\n                (f) => f.name === endFieldName,\n              );\n              if (!endField) return;\n\n              const startField = table.fields.find(\n                (f) => f.name === startFieldName,\n              );\n              if (!startField) return;\n\n              relationship.name = `fk_${startTableName}_${startFieldName}_${endTableName}`;\n              relationship.startTableId = startTableId;\n              relationship.endTableId = endTable.id;\n              relationship.endFieldId = endField.id;\n              relationship.startFieldId = startField.id;\n              relationship.id = nanoid();\n\n              let updateConstraint = Constraint.NONE;\n              let deleteConstraint = Constraint.NONE;\n              d.reference_definition.on_action.forEach((c) => {\n                if (c.type === \"on update\") {\n                  updateConstraint = c.value.value;\n                  updateConstraint =\n                    updateConstraint[0].toUpperCase() +\n                    updateConstraint.substring(1);\n                } else if (c.type === \"on delete\") {\n                  deleteConstraint = c.value.value;\n                  deleteConstraint =\n                    deleteConstraint[0].toUpperCase() +\n                    deleteConstraint.substring(1);\n                }\n              });\n\n              relationship.updateConstraint = updateConstraint;\n              relationship.deleteConstraint = deleteConstraint;\n              if (startField.unique) {\n                relationship.cardinality = Cardinality.ONE_TO_ONE;\n              } else {\n                relationship.cardinality = Cardinality.MANY_TO_ONE;\n              }\n              relationships.push(relationship);\n            }\n          }\n\n          if (d.reference_definition) {\n            const relationship = {};\n            const startTableName = table.name;\n            const startFieldName = field.name;\n            const endTableName = d.reference_definition.table[0].table;\n            const endFieldName =\n              d.reference_definition.definition[0].column.expr.value;\n            let updateConstraint = Constraint.NONE;\n            let deleteConstraint = Constraint.NONE;\n            d.reference_definition.on_action.forEach((c) => {\n              if (c.type === \"on update\") {\n                updateConstraint = c.value.value;\n                updateConstraint =\n                  updateConstraint[0].toUpperCase() +\n                  updateConstraint.substring(1);\n              } else if (c.type === \"on delete\") {\n                deleteConstraint = c.value.value;\n                deleteConstraint =\n                  deleteConstraint[0].toUpperCase() +\n                  deleteConstraint.substring(1);\n              }\n            });\n\n            const startTableId = tables.length;\n\n            const endTable = tables.find((t) => t.name === endTableName);\n            if (!endTable) return;\n\n            const endField = endTable.fields.findIndex(\n              (f) => f.name === endFieldName,\n            );\n            if (!endField) return;\n\n            const startField = table.fields.find(\n              (f) => f.name === startFieldName,\n            );\n            if (!startField) return;\n\n            relationship.name = `fk_${startTableName}_${startFieldName}_${endTableName}`;\n            relationship.startTableId = startTableId;\n            relationship.startFieldId = startField.id;\n            relationship.endTableId = endTable.id;\n            relationship.endFieldId = endField.id;\n            relationship.updateConstraint = updateConstraint;\n            relationship.deleteConstraint = deleteConstraint;\n            relationship.id = nanoid();\n\n            if (startField.unique) {\n              relationship.cardinality = Cardinality.ONE_TO_ONE;\n            } else {\n              relationship.cardinality = Cardinality.MANY_TO_ONE;\n            }\n\n            relationships.push(relationship);\n          }\n        });\n        tables.push(table);\n      } else if (e.keyword === \"index\") {\n        const index = {\n          name: e.index,\n          unique: e.index_type === \"unique\",\n          fields: e.index_columns.map((f) => f.column.expr.value),\n        };\n\n        const table = tables.find((t) => t.name === e.table.table);\n\n        if (table) {\n          table.indices.push(index);\n          table.indices.forEach((i, j) => {\n            i.id = j;\n          });\n        }\n      } else if (e.keyword === \"type\") {\n        if (e.resource === \"enum\") {\n          const newEnum = {\n            name: e.name.name,\n            values: e.create_definitions.value.map((x) => x.value),\n          };\n          enums.push(newEnum);\n        } else if (Array.isArray(e.create_definitions)) {\n          const type = {\n            name: e.name.name,\n            fields: [],\n          };\n          e.create_definitions.forEach((d) => {\n            const field = {};\n            if (d.resource === \"column\") {\n              field.name = d.column.column.expr.value;\n\n              let type = d.definition.dataType;\n              if (!dbToTypes[diagramDb][type]) {\n                type = affinity[diagramDb][type];\n              }\n              field.type = type;\n            }\n            if (d.definition[\"length\"]) {\n              if (d.definition.scale) {\n                field.size = d.definition[\"length\"] + \",\" + d.definition.scale;\n              } else {\n                field.size = d.definition[\"length\"];\n              }\n            }\n\n            type.fields.push(field);\n          });\n          types.push(type);\n        }\n      }\n    } else if (e.type === \"alter\") {\n      if (Array.isArray(e.expr)) {\n        e.expr.forEach((expr) => {\n          if (\n            expr.action === \"add\" &&\n            expr.create_definitions.constraint_type.toLowerCase() ===\n              \"foreign key\"\n          ) {\n            const relationship = {};\n            const startTableName = e.table[0].table;\n            const startFieldName =\n              expr.create_definitions.definition[0].column.expr.value;\n            const endTableName =\n              expr.create_definitions.reference_definition.table[0].table;\n            const endFieldName =\n              expr.create_definitions.reference_definition.definition[0].column\n                .expr.value;\n            let updateConstraint = Constraint.NONE;\n            let deleteConstraint = Constraint.NONE;\n            expr.create_definitions.reference_definition.on_action.forEach(\n              (c) => {\n                if (c.type === \"on update\") {\n                  updateConstraint = c.value.value;\n                  updateConstraint =\n                    updateConstraint[0].toUpperCase() +\n                    updateConstraint.substring(1);\n                } else if (c.type === \"on delete\") {\n                  deleteConstraint = c.value.value;\n                  deleteConstraint =\n                    deleteConstraint[0].toUpperCase() +\n                    deleteConstraint.substring(1);\n                }\n              },\n            );\n\n            const startTable = tables.find((t) => t.name === startTableName);\n            if (!startTable) return;\n\n            const endTable = tables.find((t) => t.name === endTableName);\n            if (!endTable) return;\n\n            const endField = endTable.fields.find(\n              (f) => f.name === endFieldName,\n            );\n            if (!endField) return;\n\n            const startField = startTable.fields.find(\n              (f) => f.name === startFieldName,\n            );\n            if (!startField) return;\n\n            relationship.name = `fk_${startTableName}_${startFieldName}_${endTableName}`;\n            relationship.startTableId = startTable.id;\n            relationship.startFieldId = startField.id;\n            relationship.endTableId = endTable.id;\n            relationship.endFieldId = endField.id;\n            relationship.updateConstraint = updateConstraint;\n            relationship.deleteConstraint = deleteConstraint;\n            relationship.cardinality = Cardinality.ONE_TO_ONE;\n            relationship.id = nanoid();\n\n            if (startField.unique) {\n              relationship.cardinality = Cardinality.ONE_TO_ONE;\n            } else {\n              relationship.cardinality = Cardinality.MANY_TO_ONE;\n            }\n\n            relationships.push(relationship);\n          }\n        });\n      }\n    } else if (e.type === \"comment\") {\n      if (e.target.type === \"table\") {\n        const table = tables.find((t) => t.name === e.target?.name?.table);\n        if (table) {\n          table.comment = e.expr.expr.value;\n        }\n      } else if (e.target.type === \"column\") {\n        const table = tables.find((t) => t.name === e.target?.name?.table);\n        if (table) {\n          const field = table.fields.find(\n            (f) => f.name === e.target?.name?.column?.expr?.value,\n          );\n          if (field) {\n            field.comment = e.expr.expr.value;\n          }\n        }\n      }\n    }\n  };\n\n  if (Array.isArray(ast)) {\n    ast.forEach((e) => parseSingleStatement(e));\n  } else {\n    parseSingleStatement(ast);\n  }\n\n  return { tables, relationships, types, enums };\n}\n"
  },
  {
    "path": "src/utils/importSQL/shared.js",
    "content": "import { DB } from \"../../data/constants\";\n\nfunction quoteColumn(str, db) {\n  switch (db) {\n    case DB.MYSQL:\n      return `\\`${str}\\``;\n    case DB.SQLITE:\n      return `\"${str}\"`;\n    case DB.POSTGRES:\n      return `\"${str}\"`;\n    case DB.MSSQL:\n      return `[${str}]`;\n    case DB.MARIADB:\n      return `\\`${str}\\``;\n  }\n}\n\nexport function buildSQLFromAST(ast, db = DB.MYSQL) {\n  if (ast.type === \"binary_expr\") {\n    const leftSQL = buildSQLFromAST(ast.left, db);\n    const rightSQL = buildSQLFromAST(ast.right, db);\n    return `${leftSQL} ${ast.operator} ${rightSQL}`;\n  }\n\n  if (ast.type === \"function\") {\n    let expr = \"\";\n    expr = ast.name;\n    if (ast.args) {\n      expr +=\n        \"(\" +\n        ast.args.value\n          .map((v) => {\n            if (v.type === \"column_ref\") return \"`\" + v.column + \"`\";\n            if (\n              v.type === \"single_quote_string\" ||\n              v.type === \"double_quote_string\"\n            )\n              return \"'\" + v.value + \"'\";\n            return v.value;\n          })\n          .join(\", \") +\n        \")\";\n    }\n    return expr;\n  } else if (ast.type === \"column_ref\") {\n    return quoteColumn(ast.column, db);\n  } else if (ast.type === \"expr_list\") {\n    return ast.value.map((v) => v.value).join(\" AND \");\n  } else {\n    return typeof ast.value === \"string\" ? \"'\" + ast.value + \"'\" : ast.value;\n  }\n}\n"
  },
  {
    "path": "src/utils/importSQL/sqlite.js",
    "content": "import { nanoid } from \"nanoid\";\nimport { Cardinality, DB } from \"../../data/constants\";\nimport { dbToTypes } from \"../../data/datatypes\";\nimport { buildSQLFromAST } from \"./shared\";\n\nconst affinity = {\n  [DB.SQLITE]: new Proxy(\n    {\n      INT: \"INTEGER\",\n      TINYINT: \"INTEGER\",\n      SMALLINT: \"INTEGER\",\n      MEDIUMINT: \"INTEGER\",\n      BIGINT: \"INTEGER\",\n      \"UNSIGNED BIG INT\": \"INTEGER\",\n      INT2: \"INTEGER\",\n      INT8: \"INTEGER\",\n      CHARACTER: \"TEXT\",\n      NCHARACTER: \"TEXT\",\n      NVARCHAR: \"VARCHAR\",\n      DOUBLE: \"REAL\",\n      FLOAT: \"REAL\",\n    },\n    { get: (target, prop) => (prop in target ? target[prop] : \"BLOB\") },\n  ),\n  [DB.GENERIC]: new Proxy(\n    {\n      INTEGER: \"INT\",\n      TINYINT: \"SMALLINT\",\n      MEDIUMINT: \"INTEGER\",\n      INT2: \"INTEGER\",\n      INT8: \"INTEGER\",\n      CHARACTER: \"TEXT\",\n      NCHARACTER: \"TEXT\",\n      NVARCHAR: \"VARCHAR\",\n    },\n    { get: (target, prop) => (prop in target ? target[prop] : \"BLOB\") },\n  ),\n};\n\nexport function fromSQLite(ast, diagramDb = DB.GENERIC) {\n  const tables = [];\n  const relationships = [];\n\n  const addRelationshipFromReferenceDef = (\n    startTable,\n    startFieldName,\n    referenceDefinition,\n  ) => {\n    const relationship = {};\n    const endTableName = referenceDefinition.table[0].table;\n    const endFieldName = referenceDefinition.definition[0].column;\n\n    const endTable = tables.find((t) => t.name === endTableName);\n    if (!endTable) return;\n\n    const endField = endTable.fields.find((f) => f.name === endFieldName);\n    if (!endField) return;\n\n    const startField = startTable.fields.find((f) => f.name === startFieldName);\n    if (!startField) return;\n\n    relationship.name =\n      \"fk_\" + startTable.name + \"_\" + startFieldName + \"_\" + endTableName;\n    relationship.startTableId = startTable.id;\n    relationship.endTableId = endTable.id;\n    relationship.endFieldId = endField.id;\n    relationship.startFieldId = startField.id;\n    relationship.id = nanoid();\n\n    let updateConstraint = \"No action\";\n    let deleteConstraint = \"No action\";\n    referenceDefinition.on_action.forEach((c) => {\n      if (c.type === \"on update\") {\n        updateConstraint = c.value.value;\n        updateConstraint =\n          updateConstraint[0].toUpperCase() + updateConstraint.substring(1);\n      } else if (c.type === \"on delete\") {\n        deleteConstraint = c.value.value;\n        deleteConstraint =\n          deleteConstraint[0].toUpperCase() + deleteConstraint.substring(1);\n      }\n    });\n\n    relationship.updateConstraint = updateConstraint;\n    relationship.deleteConstraint = deleteConstraint;\n\n    if (startField.unique) {\n      relationship.cardinality = Cardinality.ONE_TO_ONE;\n    } else {\n      relationship.cardinality = Cardinality.MANY_TO_ONE;\n    }\n    relationships.push(relationship);\n  };\n\n  const parseSingleStatement = (e) => {\n    if (e.type === \"create\") {\n      if (e.keyword === \"table\") {\n        const table = {};\n        table.name = e.table[0].table;\n        table.comment = \"\";\n        table.color = \"#175e7a\";\n        table.fields = [];\n        table.indices = [];\n        table.id = nanoid();\n        e.create_definitions.forEach((d) => {\n          if (d.resource === \"column\") {\n            const field = {};\n            field.id = nanoid();\n            field.name = d.column.column;\n\n            let type = d.definition.dataType;\n            if (!dbToTypes[diagramDb][type]) {\n              type = affinity[diagramDb][type];\n            }\n            field.type = type;\n\n            if (d.definition.expr && d.definition.expr.type === \"expr_list\") {\n              field.values = d.definition.expr.value.map((v) => v.value);\n            }\n            field.comment = d.comment ? d.comment.value.value : \"\";\n            field.unique = false;\n            if (d.unique) field.unique = true;\n            field.increment = false;\n            if (d.auto_increment) field.increment = true;\n            field.notNull = false;\n            if (d.nullable) field.notNull = true;\n            field.primary = false;\n            if (d.primary_key) field.primary = true;\n            field.default = \"\";\n            if (d.default_val) {\n              let defaultValue = \"\";\n              if (d.default_val.value.type === \"function\") {\n                defaultValue = d.default_val.value.name.name[0].value;\n                if (d.default_val.value.args) {\n                  defaultValue +=\n                    \"(\" +\n                    d.default_val.value.args.value\n                      .map((v) => {\n                        if (\n                          v.type === \"single_quote_string\" ||\n                          v.type === \"double_quote_string\"\n                        )\n                          return \"'\" + v.value + \"'\";\n                        return v.value;\n                      })\n                      .join(\", \") +\n                    \")\";\n                }\n              } else if (d.default_val.value.type === \"null\") {\n                defaultValue = \"NULL\";\n              } else {\n                defaultValue = d.default_val.value.value.toString();\n              }\n              field.default = defaultValue;\n            }\n            if (d.definition[\"length\"]) {\n              if (d.definition.scale) {\n                field.size = d.definition[\"length\"] + \",\" + d.definition.scale;\n              } else {\n                field.size = d.definition[\"length\"];\n              }\n            }\n            field.check = \"\";\n            if (d.check) {\n              field.check = buildSQLFromAST(d.check.definition[0], DB.SQLITE);\n            }\n            table.fields.push(field);\n\n            if (d.reference_definition) {\n              addRelationshipFromReferenceDef(\n                table,\n                field.name,\n                d.reference_definition,\n              );\n            }\n          } else if (d.resource === \"constraint\") {\n            if (d.constraint_type === \"primary key\") {\n              d.definition.forEach((c) => {\n                table.fields.forEach((f) => {\n                  if (f.name === c.column && !f.primary) {\n                    f.primary = true;\n                  }\n                });\n              });\n            } else if (d.constraint_type.toLowerCase() === \"foreign key\") {\n              addRelationshipFromReferenceDef(\n                table,\n                d.definition[0].column,\n                d.reference_definition,\n              );\n            }\n          }\n        });\n        tables.push(table);\n      } else if (e.keyword === \"index\") {\n        const index = {\n          name: e.index,\n          unique: e.index_type === \"unique\",\n          fields: e.index_columns.map((f) => f.column),\n        };\n\n        const table = tables.find((t) => t.name === e.table.table);\n\n        if (table) {\n          table.indices.push(index);\n          table.indices.forEach((i, j) => {\n            i.id = j;\n          });\n        }\n      }\n    }\n  };\n\n  if (Array.isArray(ast)) {\n    ast.forEach((e) => parseSingleStatement(e));\n  } else {\n    parseSingleStatement(ast);\n  }\n\n  return { tables, relationships };\n}\n"
  },
  {
    "path": "src/utils/issues.js",
    "content": "import { dbToTypes } from \"../data/datatypes\";\nimport i18n from \"../i18n/i18n\";\nimport { isFunction } from \"./utils\";\n\nfunction checkDefault(field, database) {\n  if (field.default === \"\") return true;\n  if (isFunction(field.default)) return true;\n  if (\n    !field.notNull &&\n    typeof field.default === \"string\" &&\n    field.default.toLowerCase() === \"null\"\n  )\n    return true;\n  if (!dbToTypes[database][field.type].checkDefault) return true;\n\n  return dbToTypes[database][field.type].checkDefault(field);\n}\n\nexport function getIssues(diagram) {\n  const issues = [];\n  const duplicateTableNames = {};\n\n  diagram.tables.forEach((table) => {\n    if (table.name === \"\") {\n      issues.push(i18n.t(\"table_w_no_name\"));\n    }\n\n    if (duplicateTableNames[table.name]) {\n      issues.push(i18n.t(\"duplicate_table_by_name\", { tableName: table.name }));\n    } else {\n      duplicateTableNames[table.name] = true;\n    }\n\n    const duplicateFieldNames = {};\n    let hasPrimaryKey = false;\n\n    const inheritedFields =\n      table.inherits\n        ?.map((parentName) => {\n          const parent = diagram.tables.find((t) => t.name === parentName);\n          return parent ? parent.fields.map((f) => f.name) : [];\n        })\n        .flat() || [];\n\n    table.fields.forEach((field) => {\n      if (field.primary) hasPrimaryKey = true;\n\n      if (field.name === \"\") {\n        issues.push(i18n.t(\"empty_field_name\", { tableName: table.name }));\n      }\n\n      if (field.type === \"\") {\n        issues.push(i18n.t(\"empty_field_type\", { tableName: table.name }));\n      } else if (field.type === \"ENUM\" || field.type === \"SET\") {\n        if (!field.values || field.values.length === 0) {\n          issues.push(\n            i18n.t(\"no_values_for_field\", {\n              tableName: table.name,\n              fieldName: field.name,\n              type: field.type,\n            }),\n          );\n        }\n      }\n\n      if (!checkDefault(field, diagram.database)) {\n        issues.push(\n          i18n.t(\"default_doesnt_match_type\", {\n            tableName: table.name,\n            fieldName: field.name,\n          }),\n        );\n      }\n\n      if (\n        field.notNull &&\n        typeof field.default === \"string\" &&\n        field.default.toLowerCase() === \"null\"\n      ) {\n        issues.push(\n          i18n.t(\"not_null_is_null\", {\n            tableName: table.name,\n            fieldName: field.name,\n          }),\n        );\n      }\n\n      if (duplicateFieldNames[field.name]) {\n        issues.push(\n          i18n.t(\"duplicate_fields\", {\n            tableName: table.name,\n            fieldName: field.name,\n          }),\n        );\n      } else {\n        duplicateFieldNames[field.name] = true;\n      }\n\n      if (inheritedFields.includes(field.name)) {\n        issues.push(\n          i18n.t(\"merging_column_w_inherited_definition\", {\n            fieldName: field.name,\n            tableName: table.name,\n          }),\n        );\n      }\n    });\n\n    const duplicateIndices = {};\n    table.indices.forEach((index) => {\n      if (duplicateIndices[index.name]) {\n        issues.push(\n          i18n.t(\"duplicate_index\", {\n            tableName: table.name,\n            indexName: index.name,\n          }),\n        );\n      } else {\n        duplicateIndices[index.name] = true;\n      }\n    });\n\n    table.indices.forEach((index) => {\n      if (index.name.trim() === \"\") {\n        issues.push(i18n.t(\"empty_index_name\", { tableName: table.name }));\n      }\n      if (index.fields.length === 0) {\n        issues.push(i18n.t(\"empty_index\", { tableName: table.name }));\n      }\n    });\n\n    if (!hasPrimaryKey) {\n      issues.push(i18n.t(\"no_primary_key\", { tableName: table.name }));\n    }\n  });\n\n  const duplicateTypeNames = {};\n  diagram.types.forEach((type) => {\n    if (type.name === \"\") {\n      issues.push(i18n.t(\"type_with_no_name\"));\n    }\n\n    if (duplicateTypeNames[type.name]) {\n      issues.push(i18n.t(\"duplicate_types\", { typeName: type.name }));\n    } else {\n      duplicateTypeNames[type.name] = true;\n    }\n\n    if (type.fields.length === 0) {\n      issues.push(i18n.t(\"type_w_no_fields\", { typeName: type.name }));\n      return;\n    }\n\n    const duplicateFieldNames = {};\n    type.fields.forEach((field) => {\n      if (field.name === \"\") {\n        issues.push(i18n.t(\"empty_type_field_name\", { typeName: type.name }));\n      }\n\n      if (field.type === \"\") {\n        issues.push(i18n.t(\"empty_type_field_type\", { typeName: type.name }));\n      } else if (field.type === \"ENUM\" || field.type === \"SET\") {\n        if (!field.values || field.values.length === 0) {\n          issues.push(\n            i18n.t(\"no_values_for_type_field\", {\n              typeName: type.name,\n              fieldName: field.name,\n              type: field.type,\n            }),\n          );\n        }\n      }\n\n      if (duplicateFieldNames[field.name]) {\n        issues.push(\n          i18n.t(\"duplicate_type_fields\", {\n            typeName: type.name,\n            fieldName: field.name,\n          }),\n        );\n      } else {\n        duplicateFieldNames[field.name] = true;\n      }\n    });\n  });\n\n  const duplicateEnumNames = {};\n  diagram.enums.forEach((e) => {\n    if (e.name === \"\") {\n      issues.push(i18n.t(\"enum_w_no_name\"));\n    }\n\n    if (duplicateEnumNames[e.name]) {\n      issues.push(i18n.t(\"duplicate_enums\", { enumName: e.name }));\n    } else {\n      duplicateEnumNames[e.name] = true;\n    }\n\n    if (e.values.length === 0) {\n      issues.push(i18n.t(\"enum_w_no_values\", { enumName: e.name }));\n      return;\n    }\n  });\n\n  const duplicateFKName = {};\n  diagram.relationships.forEach((r) => {\n    if (duplicateFKName[r.name]) {\n      issues.push(i18n.t(\"duplicate_reference\", { refName: r.name }));\n    } else {\n      duplicateFKName[r.name] = true;\n    }\n  });\n\n  const visitedTables = new Set();\n\n  function checkCircularRelationships(tableId, visited = []) {\n    if (visited.includes(tableId)) {\n      issues.push(\n        i18n.t(\"circular_dependency\", {\n          refName: diagram.tables.find((t) => t.id === tableId)?.name,\n        }),\n      );\n      return;\n    }\n\n    visited.push(tableId);\n    visitedTables.add(tableId);\n\n    diagram.relationships.forEach((r) => {\n      if (r.startTableId === tableId && r.startTableId !== r.endTableId) {\n        checkCircularRelationships(r.endTableId, [...visited]);\n      }\n    });\n  }\n\n  diagram.tables.forEach((table) => {\n    if (!visitedTables.has(table.id)) {\n      checkCircularRelationships(table.id);\n    }\n  });\n\n  return issues;\n}\n"
  },
  {
    "path": "src/utils/migrations/diffToSQL.js",
    "content": "import {\n  escapeQuotes,\n  parseDefault,\n  exportFieldComment,\n} from \"../exportSQL/shared\";\nimport { DB } from \"../../data/constants\";\nimport { databases } from \"../../data/databases\";\nimport { dbToTypes } from \"../../data/datatypes\";\n\nfunction getQuote(db) {\n  if (db === DB.MYSQL || db === DB.MARIADB) return (s) => `\\`${s}\\``;\n  if (db === DB.MSSQL) return (s) => `[${s}]`;\n  return (s) => `\"${s}\"`;\n}\n\nfunction parseType(field, db) {\n  let res = field.type;\n  const meta = dbToTypes[db]?.[field.type];\n  if (field.type === \"SET\" || field.type === \"ENUM\") {\n    res += field.values\n      ? `(${field.values.map((v) => `'${v}'`).join(\", \")})`\n      : \"\";\n  } else if (meta?.isSized || meta?.hasPrecision) {\n    res += field.size ? `(${field.size})` : \"\";\n  }\n  return res;\n}\n\nfunction columnDefinition(field, db) {\n  const meta =\n    dbToTypes[db]?.[field.type] || dbToTypes[DB.GENERIC]?.[field.type];\n\n  let typeStr = field.type;\n  if (db === DB.MYSQL || db === DB.MARIADB) {\n    typeStr = parseType(field, db);\n  } else if (meta?.isSized || meta?.hasPrecision) {\n    typeStr += field.size ? `(${field.size})` : \"\";\n  }\n\n  let sql = typeStr;\n\n  if (db === DB.MYSQL || db === DB.MARIADB) {\n    if (meta?.signed && field.unsigned) sql += \" UNSIGNED\";\n  }\n  if (field.notNull) sql += \" NOT NULL\";\n  if (field.unique) sql += \" UNIQUE\";\n  if (field.primary) sql += \" PRIMARY KEY\";\n\n  if (field.increment) {\n    if (db === DB.POSTGRES) sql += \" GENERATED BY DEFAULT AS IDENTITY\";\n    else if (db === DB.MYSQL || db === DB.MARIADB) sql += \" AUTO_INCREMENT\";\n    else if (db === DB.MSSQL) sql += \" IDENTITY\";\n    else if (db === DB.ORACLESQL) sql += \" GENERATED BY DEFAULT AS IDENTITY\";\n    else if (db === DB.SQLITE) sql += \" AUTOINCREMENT\";\n  }\n\n  if (field.default != null && field.default !== \"\") {\n    sql += ` DEFAULT ${parseDefault(field, db)}`;\n  }\n  if (field.check && meta?.hasCheck) sql += ` CHECK(${field.check})`;\n  if ((db === DB.MYSQL || db === DB.MARIADB) && field.comment?.trim()) {\n    sql += ` COMMENT '${escapeQuotes(field.comment)}'`;\n  }\n  if (db === DB.POSTGRES && field.isArray) sql += \" ARRAY\";\n\n  return sql;\n}\n\nfunction toTable(table, db) {\n  const q = getQuote(db);\n  const meta = (f) =>\n    dbToTypes[db]?.[f.type] || dbToTypes[DB.GENERIC]?.[f.type];\n\n  let fieldDefs;\n  if (db === DB.POSTGRES) {\n    fieldDefs = table.fields\n      .map(\n        (f) =>\n          `${exportFieldComment(f.comment)}\\t${q(f.name)} ${f.type}${f.size ? `(${f.size})` : \"\"}${f.isArray ? \" ARRAY\" : \"\"}${f.notNull ? \" NOT NULL\" : \"\"}${f.unique ? \" UNIQUE\" : \"\"}${f.increment ? \" GENERATED BY DEFAULT AS IDENTITY\" : \"\"}${f.default?.trim() ? ` DEFAULT ${parseDefault(f, db)}` : \"\"}${f.check && meta(f)?.hasCheck ? ` CHECK(${f.check})` : \"\"}`,\n      )\n      .join(\",\\n\");\n  } else if (db === DB.MYSQL || db === DB.MARIADB) {\n    fieldDefs = table.fields\n      .map(\n        (f) =>\n          `\\t${q(f.name)} ${parseType(f, db)}${db === DB.MYSQL && meta(f)?.signed && f.unsigned ? \" UNSIGNED\" : \"\"}${f.notNull ? \" NOT NULL\" : \"\"}${f.increment ? \" AUTO_INCREMENT\" : \"\"}${f.unique ? \" UNIQUE\" : \"\"}${f.default !== \"\" ? ` DEFAULT ${parseDefault(f, db)}` : \"\"}${f.check && meta(f)?.hasCheck ? ` CHECK(${f.check})` : \"\"}${f.comment ? ` COMMENT '${escapeQuotes(f.comment)}'` : \"\"}`,\n      )\n      .join(\",\\n\");\n  } else if (db === DB.SQLITE) {\n    fieldDefs = table.fields\n      .map(\n        (f) =>\n          `\\t${q(f.name)} ${f.type}${f.notNull ? \" NOT NULL\" : \"\"}${f.unique ? \" UNIQUE\" : \"\"}${f.default !== \"\" ? ` DEFAULT ${parseDefault(f, db)}` : \"\"}${f.check && meta(f)?.hasCheck ? ` CHECK(${f.check})` : \"\"}`,\n      )\n      .join(\",\\n\");\n  } else if (db === DB.MSSQL) {\n    const m = (f) => dbToTypes[DB.MSSQL]?.[f.type.toUpperCase()];\n    fieldDefs = table.fields\n      .map((f) => {\n        const isSized = m(f)?.isSized || m(f)?.hasPrecision;\n        return `\\t${q(f.name)} ${f.type}${f.size && isSized ? `(${f.size})` : \"\"}${f.notNull ? \" NOT NULL\" : \"\"}${f.increment ? \" IDENTITY\" : \"\"}${f.unique ? \" UNIQUE\" : \"\"}${f.default !== \"\" ? ` DEFAULT ${parseDefault(f, db)}` : \"\"}${f.check && meta(f)?.hasCheck ? ` CHECK(${f.check})` : \"\"}`;\n      })\n      .join(\",\\n\");\n  } else if (db === DB.ORACLESQL) {\n    fieldDefs = table.fields\n      .map(\n        (f) =>\n          `\\t${q(f.name)} ${f.type}${f.size !== undefined && f.size !== \"\" ? `(${f.size})` : \"\"}${f.notNull ? \" NOT NULL\" : \"\"}${f.increment ? \" GENERATED BY DEFAULT AS IDENTITY\" : \"\"}${f.unique ? \" UNIQUE\" : \"\"}${f.default !== \"\" ? ` DEFAULT ${parseDefault(f, db)}` : \"\"}${f.check && meta(f)?.hasCheck ? ` CHECK(${f.check})` : \"\"}`,\n      )\n      .join(\",\\n\");\n  }\n\n  const pk = table.fields.filter((f) => f.primary);\n  const pkClause =\n    pk.length > 0\n      ? `,\\n\\tPRIMARY KEY(${pk.map((f) => q(f.name)).join(\", \")})`\n      : \"\";\n\n  let inheritsClause = \"\";\n  if (\n    db === DB.POSTGRES &&\n    Array.isArray(table.inherits) &&\n    table.inherits.length > 0\n  ) {\n    inheritsClause = `\\n) INHERITS (${table.inherits.map((p) => q(p)).join(\", \")})`;\n  } else {\n    inheritsClause = \"\\n)\";\n  }\n\n  let create = \"\";\n  if (db === DB.POSTGRES || db === DB.MYSQL || db === DB.SQLITE) {\n    create = `CREATE TABLE IF NOT EXISTS ${q(table.name)} (\\n${fieldDefs}${pkClause}${inheritsClause};`;\n  } else if (db === DB.MARIADB) {\n    create = `CREATE OR REPLACE TABLE ${q(table.name)} (\\n${fieldDefs}${pkClause}\\n)`;\n  } else if (db === DB.MSSQL) {\n    create = `CREATE TABLE ${q(table.name)} (\\n${fieldDefs}${pkClause}\\n);\\nGO`;\n  } else if (db === DB.ORACLESQL) {\n    create = `CREATE TABLE ${q(table.name)} (\\n${fieldDefs}${pkClause}\\n)`;\n  }\n\n  if (db === DB.MARIADB || db === DB.ORACLESQL) create += \";\";\n\n  if ((db === DB.MYSQL || db === DB.MARIADB) && table.comment?.trim()) {\n    create = create.replace(\n      \");\",\n      `) COMMENT='${escapeQuotes(table.comment)}';`,\n    );\n  }\n\n  let extra = \"\";\n  if (db === DB.POSTGRES || db === DB.ORACLESQL) {\n    const t = table.comment?.trim()\n      ? `COMMENT ON TABLE ${q(table.name)} IS '${escapeQuotes(table.comment)}';`\n      : \"\";\n    const cols = table.fields\n      .filter((f) => f.comment?.trim())\n      .map(\n        (f) =>\n          `COMMENT ON COLUMN ${q(table.name)}.${q(f.name)} IS '${escapeQuotes(f.comment)}'`,\n      )\n      .join(\";\\n\");\n    extra = [t, cols].filter(Boolean).join(\"\\n\");\n  } else if (db === DB.MSSQL && table.comment?.trim()) {\n    extra = `\nEXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'${escapeQuotes(table.comment).replace(/'/g, \"''\")}',\n  @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'${table.name}';\nGO`;\n  }\n\n  const indexStmts = (table.indices || [])\n    .map((i) => {\n      const ifNotExists = db === DB.SQLITE ? \"IF NOT EXISTS \" : \"\";\n      const idx = `CREATE ${i.unique ? \"UNIQUE \" : \"\"}INDEX ${ifNotExists}${q(i.name)}\\nON ${q(table.name)} (${(i.fields || []).map((c) => q(c)).join(\", \")});`;\n      return db === DB.MSSQL ? idx + \"\\nGO\" : idx;\n    })\n    .join(\"\\n\");\n\n  const prefix =\n    db === DB.SQLITE && table.comment?.trim()\n      ? `/* ${escapeQuotes(table.comment)} */\\n`\n      : \"\";\n  return [prefix, create, extra, indexStmts].filter(Boolean).join(\"\\n\");\n}\n\nfunction resolveRel(diagram, rel) {\n  const tables = diagram?.tables || [];\n  const startT = tables.find((t) => t.id === rel.startTableId);\n  const endT = tables.find((t) => t.id === rel.endTableId);\n  if (!startT || !endT) return null;\n  const startF = (startT.fields || []).find((f) => f.id === rel.startFieldId);\n  const endF = (endT.fields || []).find((f) => f.id === rel.endFieldId);\n  if (!startF || !endF) return null;\n  return {\n    startTableName: startT.name,\n    startFieldName: startF.name,\n    endTableName: endT.name,\n    endFieldName: endF.name,\n  };\n}\n\nfunction normalizeFkAction(s) {\n  return (s || \"No action\").toString().toUpperCase();\n}\n\nfunction toTypeDefinition(type, database, q) {\n  if (!type || !databases[database]?.hasTypes) return null;\n  const fields = (type.fields || [])\n    .map((f) => `\\t${q(f.name)} ${f.type}`)\n    .join(\",\\n\");\n  let s = `CREATE TYPE ${q(type.name)} AS (\\n${fields}\\n);`;\n  if (type.comment?.trim()) {\n    s += `\\nCOMMENT ON TYPE ${q(type.name)} IS '${escapeQuotes(type.comment)}';`;\n  }\n  return s;\n}\n\nfunction toEnumDefinition(e, database, q) {\n  if (!e || !databases[database]?.hasEnums) return null;\n  const values = (e.values || [])\n    .map((v) => `\\t'${escapeQuotes(String(v))}'`)\n    .join(\",\\n\");\n  return `CREATE TYPE ${q(e.name)} AS ENUM (\\n${values}\\n);`;\n}\n\nexport const generateMigrationSQL = (\n  diff,\n  database = DB.POSTGRES,\n  diagrams,\n) => {\n  const q = getQuote(database);\n  let up = [];\n  let down = [];\n\n  for (const [path, change] of Object.entries(diff)) {\n    const keys = path.split(\"#\");\n    const bracketStart = keys[0].indexOf(\"[\");\n    const element =\n      bracketStart >= 0 ? keys[0].substring(0, bracketStart) : keys[0];\n    const nameStart = keys[0].indexOf(\"name=\");\n    const name =\n      nameStart >= 0\n        ? keys[0].substring(nameStart + 5, keys[0].indexOf(\"]\", nameStart))\n        : \"\";\n\n    switch (element) {\n      case \"tables\": {\n        if (keys.length === 1 && change.from && !change.to) {\n          up.push(`DROP TABLE ${q(change.from.name)};`);\n          down.push(toTable(change.from, database));\n        }\n        if (keys.length === 1 && change.to && !change.from) {\n          up.push(toTable(change.to, database));\n          down.push(`DROP TABLE ${q(change.to.name)};`);\n        }\n\n        if (keys.length > 1) {\n          const childPart = keys[1];\n\n          if (childPart.startsWith(\"fields\")) {\n            const columnName = childPart.substring(\n              childPart.indexOf(\"name=\") + 5,\n              childPart.indexOf(\",type=\"),\n            );\n            const columnType = childPart.substring(\n              childPart.indexOf(\"type=\") + 5,\n              childPart.indexOf(\"]\"),\n            );\n\n            const property = keys[2];\n\n            if (!property) {\n              if (change.from && !change.to) {\n                up.push(`ALTER TABLE ${q(name)} DROP COLUMN ${q(columnName)};`);\n                const addCol =\n                  database === DB.MSSQL\n                    ? `ADD ${q(columnName)} ${columnDefinition(change.from, database)}`\n                    : database === DB.ORACLESQL\n                      ? `ADD (${q(columnName)} ${columnDefinition(change.from, database)})`\n                      : `ADD COLUMN ${q(columnName)} ${columnDefinition(change.from, database)}`;\n                down.push(`ALTER TABLE ${q(name)} ${addCol};`);\n              }\n              if (change.to && !change.from) {\n                const addCol =\n                  database === DB.MSSQL\n                    ? `ADD ${q(columnName)} ${columnDefinition(change.to, database)}`\n                    : database === DB.ORACLESQL\n                      ? `ADD (${q(columnName)} ${columnDefinition(change.to, database)})`\n                      : `ADD COLUMN ${q(columnName)} ${columnDefinition(change.to, database)}`;\n                up.push(`ALTER TABLE ${q(name)} ${addCol};`);\n                down.push(\n                  `ALTER TABLE ${q(name)} DROP COLUMN ${q(columnName)};`,\n                );\n              }\n            }\n\n            switch (property) {\n              case \"type\": {\n                if (database === DB.SQLITE) {\n                  break;\n                }\n                if (database === DB.MYSQL || database === DB.MARIADB) {\n                  up.push(\n                    `ALTER TABLE ${q(name)} MODIFY COLUMN ${q(columnName)} ${change.to};`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} MODIFY COLUMN ${q(columnName)} ${change.from};`,\n                  );\n                } else if (database === DB.ORACLESQL) {\n                  up.push(\n                    `ALTER TABLE ${q(name)} MODIFY (${q(columnName)} ${change.to});`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} MODIFY (${q(columnName)} ${change.from});`,\n                  );\n                } else {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} TYPE ${change.to};`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} TYPE ${change.from};`,\n                  );\n                }\n                break;\n              }\n\n              case \"notNull\": {\n                if (database === DB.SQLITE) {\n                  break;\n                } else {\n                  const nn =\n                    database === DB.MYSQL || database === DB.MARIADB\n                      ? (v) =>\n                          `ALTER TABLE ${q(name)} MODIFY COLUMN ${q(columnName)} ${columnType}${v ? \" NOT NULL\" : \"\"};`\n                      : (v) =>\n                          `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} ${v ? \"SET NOT NULL\" : \"DROP NOT NULL\"};`;\n                  if (change.to) {\n                    up.push(nn(true));\n                    down.push(nn(false));\n                  } else {\n                    up.push(nn(false));\n                    down.push(nn(true));\n                  }\n                }\n                break;\n              }\n\n              case \"default\": {\n                const defVal = (v) =>\n                  parseDefault(\n                    { default: v, type: columnType || \"VARCHAR\" },\n                    database,\n                  );\n                if (change.to != null && change.to !== \"\") {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} SET DEFAULT ${defVal(change.to)};`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} DROP DEFAULT;`,\n                  );\n                } else {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} DROP DEFAULT;`,\n                  );\n                  if (change.from != null && change.from !== \"\") {\n                    down.push(\n                      `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} SET DEFAULT ${defVal(change.from)};`,\n                    );\n                  }\n                }\n                break;\n              }\n\n              case \"check\": {\n                const cn = `${name}_${columnName}_check`;\n                if (change.to && change.to !== \"\") {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ADD CONSTRAINT ${q(cn)} CHECK (${change.to});`,\n                  );\n                  down.push(`ALTER TABLE ${q(name)} DROP CONSTRAINT ${q(cn)};`);\n                } else {\n                  up.push(`ALTER TABLE ${q(name)} DROP CONSTRAINT ${q(cn)};`);\n                  down.push(\n                    `ALTER TABLE ${q(name)} ADD CONSTRAINT ${q(cn)} CHECK (${change.from});`,\n                  );\n                }\n                break;\n              }\n\n              case \"increment\": {\n                if (change.to === true) {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} ADD GENERATED BY DEFAULT AS IDENTITY;`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} DROP IDENTITY;`,\n                  );\n                } else {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} DROP IDENTITY;`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} ADD GENERATED BY DEFAULT AS IDENTITY;`,\n                  );\n                }\n                break;\n              }\n\n              case \"isArray\": {\n                if (database !== DB.POSTGRES) break;\n\n                if (change.to === true) {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} TYPE ${columnType}[] USING ${q(columnName)}::${columnType}[];`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} TYPE ${columnType} USING ${q(columnName)}[1];`,\n                  );\n                } else {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} TYPE ${columnType} USING ${q(columnName)}[1];`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} TYPE ${columnType}[] USING ${q(columnName)}::${columnType}[];`,\n                  );\n                }\n                break;\n              }\n\n              case \"comment\": {\n                if (database === DB.MYSQL || database === DB.MARIADB) {\n                  up.push(\n                    `ALTER TABLE ${q(name)} MODIFY COLUMN ${q(columnName)} ${columnType} COMMENT '${escapeQuotes(String(change.to ?? \"\"))}';`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} MODIFY COLUMN ${q(columnName)} ${columnType} COMMENT '${escapeQuotes(String(change.from ?? \"\"))}';`,\n                  );\n                } else if (database === DB.MSSQL) {\n                  up.push(\n                    `EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'${escapeQuotes(String(change.to ?? \"\")).replace(/'/g, \"''\")}', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'${name}', @level2type=N'COLUMN',@level2name=N'${columnName}';`,\n                  );\n                  down.push(\n                    `EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'${escapeQuotes(String(change.from ?? \"\")).replace(/'/g, \"''\")}', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'${name}', @level2type=N'COLUMN',@level2name=N'${columnName}';`,\n                  );\n                } else if (database === DB.SQLITE) {\n                  up.push(\n                    `-- ${escapeQuotes(String(change.to ?? \"\"))};`,\n                  );\n                  down.push(\n                    `-- ${escapeQuotes(String(change.from ?? \"\"))};`,\n                  );\n                } else {\n                  up.push(\n                    `COMMENT ON COLUMN ${q(name)}.${q(columnName)} IS '${escapeQuotes(String(change.to ?? \"\"))}';`,\n                  );\n                  down.push(\n                    `COMMENT ON COLUMN ${q(name)}.${q(columnName)} IS '${escapeQuotes(String(change.from ?? \"\"))}';`,\n                  );\n                }\n                break;\n              }\n\n              case \"name\": {\n                if (database === DB.MSSQL) {\n                  up.push(\n                    `EXEC sp_rename '${name}.${change.from}', '${change.to}', 'COLUMN';`,\n                  );\n                  down.push(\n                    `EXEC sp_rename '${name}.${change.to}', '${change.from}', 'COLUMN';`,\n                  );\n                } else {\n                  up.push(\n                    `ALTER TABLE ${q(name)} RENAME COLUMN ${q(change.from)} TO ${q(change.to)};`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} RENAME COLUMN ${q(change.to)} TO ${q(change.from)};`,\n                  );\n                }\n                break;\n              }\n\n              case \"unique\": {\n                const cu = `${name}_${columnName}_unique`;\n                if (change.to) {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ADD CONSTRAINT ${q(cu)} UNIQUE (${q(columnName)});`,\n                  );\n                  down.push(`ALTER TABLE ${q(name)} DROP CONSTRAINT ${q(cu)};`);\n                } else {\n                  up.push(`ALTER TABLE ${q(name)} DROP CONSTRAINT ${q(cu)};`);\n                  down.push(\n                    `ALTER TABLE ${q(name)} ADD CONSTRAINT ${q(cu)} UNIQUE (${q(columnName)});`,\n                  );\n                }\n                break;\n              }\n\n              case \"primary\": {\n                const cp = `${name}_pkey`;\n                if (change.to) {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ADD CONSTRAINT ${q(cp)} PRIMARY KEY (${q(columnName)});`,\n                  );\n                  down.push(`ALTER TABLE ${q(name)} DROP CONSTRAINT ${q(cp)};`);\n                } else {\n                  up.push(`ALTER TABLE ${q(name)} DROP CONSTRAINT ${q(cp)};`);\n                  down.push(\n                    `ALTER TABLE ${q(name)} ADD CONSTRAINT ${q(cp)} PRIMARY KEY (${q(columnName)});`,\n                  );\n                }\n                break;\n              }\n\n              case \"size\": {\n                if (database === DB.SQLITE) break;\n\n                if (database === DB.MYSQL || database === DB.MARIADB) {\n                  up.push(\n                    `ALTER TABLE ${q(name)} MODIFY COLUMN ${q(columnName)} ${columnType}(${change.to});`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} MODIFY COLUMN ${q(columnName)} ${columnType}(${change.from});`,\n                  );\n                } else if (database === DB.ORACLESQL) {\n                  up.push(\n                    `ALTER TABLE ${q(name)} MODIFY (${q(columnName)} ${columnType}(${change.to}));`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} MODIFY (${q(columnName)} ${columnType}(${change.from}));`,\n                  );\n                } else {\n                  up.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} TYPE ${columnType}(${change.to});`,\n                  );\n                  down.push(\n                    `ALTER TABLE ${q(name)} ALTER COLUMN ${q(columnName)} TYPE ${columnType}(${change.from});`,\n                  );\n                }\n                break;\n              }\n\n              default:\n                break;\n            }\n          }\n\n          if (childPart.startsWith(\"indices\")) {\n            const property = keys[2];\n            const idxFields = (arr) => (arr || []).map((f) => q(f)).join(\", \");\n\n            if (!property) {\n              if (change.from && !change.to) {\n                const dropIdx =\n                  database === DB.MYSQL || database === DB.MARIADB\n                    ? `DROP INDEX ${q(change.from.name)} ON ${q(name)};`\n                    : `DROP INDEX ${q(change.from.name)};`;\n                up.push(dropIdx);\n                const ifNotExists =\n                  database === DB.SQLITE ? \"IF NOT EXISTS \" : \"\";\n                down.push(\n                  `CREATE ${change.from.unique ? \"UNIQUE \" : \"\"}INDEX ${ifNotExists}${q(change.from.name)} ON ${q(name)} (${idxFields(change.from.fields)});`,\n                );\n              }\n              if (change.to && !change.from) {\n                const ifNotExists =\n                  database === DB.SQLITE ? \"IF NOT EXISTS \" : \"\";\n                up.push(\n                  `CREATE ${change.to.unique ? \"UNIQUE \" : \"\"}INDEX ${ifNotExists}${q(change.to.name)} ON ${q(name)} (${idxFields(change.to.fields)});`,\n                );\n                const dropIdx =\n                  database === DB.MYSQL || database === DB.MARIADB\n                    ? `DROP INDEX ${q(change.to.name)} ON ${q(name)};`\n                    : `DROP INDEX ${q(change.to.name)};`;\n                down.push(dropIdx);\n              }\n            }\n\n            if (property === \"name\") {\n              if (database === DB.POSTGRES || database === DB.ORACLESQL) {\n                up.push(\n                  `ALTER INDEX ${q(change.from)} RENAME TO ${q(change.to)};`,\n                );\n                down.push(\n                  `ALTER INDEX ${q(change.to)} RENAME TO ${q(change.from)};`,\n                );\n              } else {\n                up.push(\n                  `-- Rename index: DROP ${q(change.from)} then CREATE with new name`,\n                );\n                down.push(\n                  `-- Rename index: DROP ${q(change.to)} then CREATE with old name`,\n                );\n              }\n            }\n\n            if (property === \"fields\") {\n              const ns = childPart.indexOf(\"name=\");\n              const indexName =\n                ns >= 0\n                  ? childPart.substring(ns + 5, childPart.indexOf(\"]\", ns))\n                  : \"\";\n              if (\n                indexName &&\n                Array.isArray(change.from) &&\n                Array.isArray(change.to)\n              ) {\n                const dropIdx =\n                  database === DB.MYSQL || database === DB.MARIADB\n                    ? `DROP INDEX ${q(indexName)} ON ${q(name)};`\n                    : `DROP INDEX ${q(indexName)};`;\n                const ifNotExists =\n                  database === DB.SQLITE ? \"IF NOT EXISTS \" : \"\";\n                const mkCreate = (arr, unique = false) =>\n                  `CREATE ${unique ? \"UNIQUE \" : \"\"}INDEX ${ifNotExists}${q(indexName)} ON ${q(name)} (${idxFields(arr)});`;\n                up.push(dropIdx);\n                up.push(mkCreate(change.to));\n                down.push(dropIdx);\n                down.push(mkCreate(change.from));\n              }\n            }\n          }\n\n          if (childPart === \"inherits\" && keys[2] !== undefined) {\n            if (database !== DB.POSTGRES) break;\n\n            const parent = change.to || change.from;\n            if (parent) {\n              if (change.to && !change.from) {\n                up.push(`ALTER TABLE ${q(name)} INHERIT ${q(parent)};`);\n                down.push(`ALTER TABLE ${q(name)} NO INHERIT ${q(parent)};`);\n              } else if (change.from && !change.to) {\n                up.push(`ALTER TABLE ${q(name)} NO INHERIT ${q(parent)};`);\n                down.push(`ALTER TABLE ${q(name)} INHERIT ${q(parent)};`);\n              } else if (change.from && change.to) {\n                up.push(`ALTER TABLE ${q(name)} NO INHERIT ${q(change.from)};`);\n                up.push(`ALTER TABLE ${q(name)} INHERIT ${q(change.to)};`);\n                down.push(`ALTER TABLE ${q(name)} NO INHERIT ${q(change.to)};`);\n                down.push(`ALTER TABLE ${q(name)} INHERIT ${q(change.from)};`);\n              }\n            }\n          }\n\n          if (childPart === \"comment\") {\n            if (database === DB.POSTGRES || database === DB.ORACLESQL) {\n              up.push(\n                `COMMENT ON TABLE ${q(name)} IS '${escapeQuotes(String(change.to ?? \"\"))}';`,\n              );\n              down.push(\n                `COMMENT ON TABLE ${q(name)} IS '${escapeQuotes(String(change.from ?? \"\"))}';`,\n              );\n            } else if (database === DB.MYSQL || database === DB.MARIADB) {\n              up.push(\n                `ALTER TABLE ${q(name)} COMMENT='${escapeQuotes(String(change.to ?? \"\"))}';`,\n              );\n              down.push(\n                `ALTER TABLE ${q(name)} COMMENT='${escapeQuotes(String(change.from ?? \"\"))}';`,\n              );\n            } else if (database === DB.MSSQL) {\n              up.push(\n                `EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'${escapeQuotes(String(change.to ?? \"\")).replace(/'/g, \"''\")}', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'${name}';`,\n              );\n              down.push(\n                `EXEC sp_addextendedproperty @name=N'MS_Description', @value=N'${escapeQuotes(String(change.from ?? \"\")).replace(/'/g, \"''\")}', @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'${name}';`,\n              );\n            } else if (database === DB.SQLITE) {\n              up.push(\n                `-- TABLE COMMENT: ${escapeQuotes(String(change.to ?? \"\"))}`,\n              );\n              down.push(\n                `-- TABLE COMMENT: ${escapeQuotes(String(change.from ?? \"\"))}`,\n              );\n            }\n          }\n\n          if (childPart === \"name\") {\n            if (database === DB.MYSQL || database === DB.MARIADB) {\n              up.push(`RENAME TABLE ${q(change.from)} TO ${q(change.to)};`);\n              down.push(`RENAME TABLE ${q(change.to)} TO ${q(change.from)};`);\n            } else if (database === DB.MSSQL) {\n              up.push(`EXEC sp_rename '${change.from}', '${change.to}';`);\n              down.push(`EXEC sp_rename '${change.to}', '${change.from}';`);\n            } else {\n              up.push(\n                `ALTER TABLE ${q(change.from)} RENAME TO ${q(change.to)};`,\n              );\n              down.push(\n                `ALTER TABLE ${q(change.to)} RENAME TO ${q(change.from)};`,\n              );\n            }\n          }\n        }\n\n        break;\n      }\n      case \"relationships\": {\n        if (database === DB.SQLITE) break;\n\n        const getRels = (d) => d?.relationships || d?.references || [];\n\n        if (keys.length === 1) {\n          if (change.to && !change.from) {\n            const resolved = resolveRel(diagrams.to, change.to);\n            if (!resolved) break;\n\n            const addFk = `ALTER TABLE ${q(resolved.startTableName)} ADD CONSTRAINT ${q(change.to.name)} FOREIGN KEY (${q(resolved.startFieldName)}) REFERENCES ${q(resolved.endTableName)} (${q(resolved.endFieldName)}) ON UPDATE ${normalizeFkAction(change.to.updateConstraint)} ON DELETE ${normalizeFkAction(change.to.deleteConstraint)};`;\n            up.push(addFk);\n            const dropFk =\n              database === DB.MYSQL || database === DB.MARIADB\n                ? `ALTER TABLE ${q(resolved.startTableName)} DROP FOREIGN KEY ${q(change.to.name)};`\n                : `ALTER TABLE ${q(resolved.startTableName)} DROP CONSTRAINT ${q(change.to.name)};`;\n            down.push(dropFk);\n          }\n          if (change.from && !change.to) {\n            const resolved = resolveRel(diagrams.from, change.from);\n            if (!resolved) break;\n\n            const dropFk =\n              database === DB.MYSQL || database === DB.MARIADB\n                ? `ALTER TABLE ${q(resolved.startTableName)} DROP FOREIGN KEY ${q(change.from.name)};`\n                : `ALTER TABLE ${q(resolved.startTableName)} DROP CONSTRAINT ${q(change.from.name)};`;\n            up.push(dropFk);\n            const addFk = `ALTER TABLE ${q(resolved.startTableName)} ADD CONSTRAINT ${q(change.from.name)} FOREIGN KEY (${q(resolved.startFieldName)}) REFERENCES ${q(resolved.endTableName)} (${q(resolved.endFieldName)}) ON UPDATE ${normalizeFkAction(change.from.updateConstraint)} ON DELETE ${normalizeFkAction(change.from.deleteConstraint)};`;\n            down.push(addFk);\n          }\n          break;\n        }\n\n        const prop = keys[1];\n        if (\n          keys.length === 2 &&\n          (prop === \"updateConstraint\" || prop === \"deleteConstraint\")\n        ) {\n          const idMatch = keys[0].match(/id=([^,\\]]+)/);\n          const relId = idMatch ? idMatch[1] : null;\n          if (!relId) break;\n          const relTo = getRels(diagrams.to).find(\n            (r) => String(r.id) === String(relId),\n          );\n          const relFrom = getRels(diagrams.from).find(\n            (r) => String(r.id) === String(relId),\n          );\n          if (!relTo || !relFrom) {\n            break;\n          }\n          const resolvedTo = resolveRel(diagrams.to, relTo);\n          const resolvedFrom = resolveRel(diagrams.from, relFrom);\n          if (!resolvedTo || !resolvedFrom) break;\n\n          const dropFk = (resolved, rel) =>\n            database === DB.MYSQL || database === DB.MARIADB\n              ? `ALTER TABLE ${q(resolved.startTableName)} DROP FOREIGN KEY ${q(rel.name)};`\n              : `ALTER TABLE ${q(resolved.startTableName)} DROP CONSTRAINT ${q(rel.name)};`;\n          const addFk = (rel, resolved) =>\n            `ALTER TABLE ${q(resolved.startTableName)} ADD CONSTRAINT ${q(rel.name)} FOREIGN KEY (${q(resolved.startFieldName)}) REFERENCES ${q(resolved.endTableName)} (${q(resolved.endFieldName)}) ON UPDATE ${normalizeFkAction(rel.updateConstraint)} ON DELETE ${normalizeFkAction(rel.deleteConstraint)};`;\n          up.push(dropFk(resolvedTo, relTo));\n          up.push(addFk(relTo, resolvedTo));\n          down.push(dropFk(resolvedFrom, relFrom));\n          down.push(addFk(relFrom, resolvedFrom));\n        }\n        break;\n      }\n      case \"types\": {\n        if (!databases[database]?.hasTypes) break;\n\n        if (keys.length === 1) {\n          if (change.to && !change.from) {\n            up.push(toTypeDefinition(change.to, database, q));\n            down.push(`DROP TYPE ${q(change.to.name)};`);\n          }\n          if (change.from && !change.to) {\n            up.push(`DROP TYPE ${q(change.from.name)};`);\n            down.push(toTypeDefinition(change.from, database, q));\n          }\n          break;\n        }\n\n        const prop = keys[1];\n        if (prop === \"name\") {\n          up.push(`ALTER TYPE ${q(change.from)} RENAME TO ${q(change.to)};`);\n          down.push(`ALTER TYPE ${q(change.to)} RENAME TO ${q(change.from)};`);\n        }\n        if (prop === \"comment\") {\n          up.push(\n            `COMMENT ON TYPE ${q(name)} IS '${escapeQuotes(String(change.to ?? \"\"))}';`,\n          );\n          down.push(\n            `COMMENT ON TYPE ${q(name)} IS '${escapeQuotes(String(change.from ?? \"\"))}';`,\n          );\n        }\n        if (prop.startsWith(\"fields\")) {\n          const nameMatch = prop.match(/name=([^,\\]]+)/);\n          const typeMatch = prop.match(/type=([^,\\]]+)/);\n\n          const fieldName = nameMatch?.[1];\n          const fieldType = typeMatch?.[1];\n\n          if (!fieldName) break;\n\n          if (change.to && !change.from) {\n            up.push(\n              `ALTER TYPE ${q(name)} ADD ATTRIBUTE ${q(fieldName)} ${fieldType};`,\n            );\n            down.push(`ALTER TYPE ${q(name)} DROP ATTRIBUTE ${q(fieldName)};`);\n          }\n\n          if (change.from && !change.to) {\n            up.push(`ALTER TYPE ${q(name)} DROP ATTRIBUTE ${q(fieldName)};`);\n            down.push(\n              `ALTER TYPE ${q(name)} ADD ATTRIBUTE ${q(fieldName)} ${fieldType};`,\n            );\n          }\n\n          const fieldProp = keys[2];\n          if (fieldProp === \"name\") {\n            up.push(\n              `ALTER TYPE ${q(name)} RENAME ATTRIBUTE ${q(change.from)} TO ${q(change.to)};`,\n            );\n            down.push(\n              `ALTER TYPE ${q(name)} RENAME ATTRIBUTE ${q(change.to)} TO ${q(change.from)};`,\n            );\n          }\n\n          if (fieldProp === \"type\") {\n            up.push(\n              `ALTER TYPE ${q(name)} ALTER ATTRIBUTE ${q(fieldName)} SET DATA TYPE ${change.to};`,\n            );\n            down.push(\n              `ALTER TYPE ${q(name)} ALTER ATTRIBUTE ${q(fieldName)} SET DATA TYPE ${change.from};`,\n            );\n          }\n\n          break;\n        }\n\n        break;\n      }\n      case \"enums\": {\n        if (!databases[database]?.hasEnums) break;\n\n        if (keys.length === 1) {\n          if (change.to && !change.from) {\n            up.push(toEnumDefinition(change.to, database, q));\n            down.push(`DROP TYPE ${q(change.to.name)};`);\n          }\n          if (change.from && !change.to) {\n            up.push(`DROP TYPE ${q(change.from.name)};`);\n            down.push(toEnumDefinition(change.from, database, q));\n          }\n          break;\n        }\n\n        const prop = keys[1];\n        if (prop === \"name\") {\n          up.push(`ALTER TYPE ${q(change.from)} RENAME TO ${q(change.to)};`);\n          down.push(`ALTER TYPE ${q(change.to)} RENAME TO ${q(change.from)};`);\n        }\n        if (prop === \"values\") {\n          const vals = (arr) =>\n            (arr || []).map((v) => `'${escapeQuotes(String(v))}'`).join(\", \");\n          up.push(`DROP TYPE ${q(name)};`);\n          up.push(`CREATE TYPE ${q(name)} AS ENUM (${vals(change.to)});`);\n          down.push(`DROP TYPE ${q(name)};`);\n          down.push(`CREATE TYPE ${q(name)} AS ENUM (${vals(change.from)});`);\n        }\n        break;\n      }\n      default:\n        break;\n    }\n  }\n\n  return { up: up.join(\"\\n\"), down: down.join(\"\\n\") };\n};\n"
  },
  {
    "path": "src/utils/modalData.js",
    "content": "import { MODAL } from \"../data/constants\";\nimport i18n from \"../i18n/i18n\";\n\nexport const getModalTitle = (modal) => {\n  switch (modal) {\n    case MODAL.IMPORT:\n      return i18n.t(\"import_diagram\");\n    case MODAL.IMPORT_SRC:\n      return i18n.t(\"import_from_source\");\n    case MODAL.CODE:\n      return i18n.t(\"export\");\n    case MODAL.IMG:\n      return i18n.t(\"export_image\");\n    case MODAL.RENAME:\n      return i18n.t(\"rename_diagram\");\n    case MODAL.OPEN:\n      return i18n.t(\"open_diagram\");\n    case MODAL.SAVEAS:\n      return i18n.t(\"save_as\");\n    case MODAL.NEW:\n      return i18n.t(\"create_new_diagram\");\n    case MODAL.TABLE_WIDTH:\n      return i18n.t(\"table_width\");\n    case MODAL.LANGUAGE:\n      return i18n.t(\"language\");\n    case MODAL.SHARE:\n      return i18n.t(\"share\");\n    default:\n      return \"\";\n  }\n};\n\nexport const getModalWidth = (modal) => {\n  switch (modal) {\n    case MODAL.LANGUAGE:\n    case MODAL.OPEN:\n    case MODAL.CODE:\n    case MODAL.NEW:\n      return 740;\n    default:\n      return 600;\n  }\n};\n\nexport const getOkText = (modal) => {\n  switch (modal) {\n    case MODAL.IMPORT:\n    case MODAL.IMPORT_SRC:\n      return i18n.t(\"import\");\n    case MODAL.CODE:\n    case MODAL.IMG:\n      return i18n.t(\"export\");\n    case MODAL.RENAME:\n      return i18n.t(\"rename\");\n    case MODAL.OPEN:\n      return i18n.t(\"open\");\n    case MODAL.SAVEAS:\n      return i18n.t(\"save_as\");\n    case MODAL.NEW:\n      return i18n.t(\"create\");\n    case MODAL.SHARE:\n      return i18n.t(\"share\");\n    default:\n      return i18n.t(\"confirm\");\n  }\n};\n"
  },
  {
    "path": "src/utils/rect.js",
    "content": "export function getRectFromEndpoints({ x1, x2, y1, y2 }) {\n  const width = Math.abs(x1 - x2);\n  const height = Math.abs(y1 - y2);\n\n  const x = Math.min(x1, x2);\n  const y = Math.min(y1, y2);\n\n  return { x, y, width, height };\n}\n\nexport function isInsideRect(rect1, rect2) {\n  return (\n    rect1.x > rect2.x &&\n    rect1.x + rect1.width < rect2.x + rect2.width &&\n    rect1.y > rect2.y &&\n    rect1.y + rect1.height < rect2.y + rect2.height\n  );\n}\n"
  },
  {
    "path": "src/utils/utils.js",
    "content": "import { dbToTypes } from \"../data/datatypes\";\n\nimport {\n  tableFieldHeight,\n  tableHeaderHeight,\n  tableColorStripHeight,\n} from \"../data/constants\";\n\nexport function dataURItoBlob(dataUrl) {\n  const byteString = atob(dataUrl.split(\",\")[1]);\n  const mimeString = dataUrl.split(\",\")[0].split(\":\")[1].split(\";\")[0];\n  const arrayBuffer = new ArrayBuffer(byteString.length);\n  const intArray = new Uint8Array(arrayBuffer);\n\n  for (let i = 0; i < byteString.length; i++) {\n    intArray[i] = byteString.charCodeAt(i);\n  }\n\n  return new Blob([intArray], { type: mimeString });\n}\n\nexport function arrayIsEqual(arr1, arr2) {\n  return JSON.stringify(arr1) === JSON.stringify(arr2);\n}\n\nexport function strHasQuotes(str) {\n  if (str.length < 2) return false;\n\n  return (\n    (str[0] === str[str.length - 1] && str[0] === \"'\") ||\n    (str[0] === str[str.length - 1] && str[0] === '\"') ||\n    (str[0] === str[str.length - 1] && str[0] === \"`\")\n  );\n}\n\nconst keywords = [\n  \"NULL\",\n  \"TRUE\",\n  \"FALSE\",\n  \"CURRENT_DATE\",\n  \"CURRENT_TIME\",\n  \"CURRENT_TIMESTAMP\",\n  \"LOCALTIME\",\n  \"LOCALTIMESTAMP\",\n];\n\nexport function isKeyword(str) {\n  if (typeof str !== \"string\") return false;\n\n  return keywords.includes(str.toUpperCase());\n}\n\nexport function isFunction(str) {\n  return /\\w+\\([^)]*\\)$/.test(str);\n}\n\nexport function areFieldsCompatible(db, field1Type, field2Type) {\n  const same = field1Type === field2Type;\n  const isCompatible =\n    dbToTypes[db][field1Type].compatibleWith &&\n    dbToTypes[db][field1Type].compatibleWith.includes(field2Type);\n  return same || isCompatible;\n}\n\nexport function getCommentHeight(comment, containerWidth, showComments = true) {\n  if (!comment || !showComments) return 0;\n\n  const paddingBottom = 12;\n  const borders = 4;\n\n  const span = document.createElement(\"span\");\n  span.className = \"absolute text-xs px-3 line-clamp-5\";\n\n  span.style.width = containerWidth - borders + \"px\";\n  span.textContent = comment;\n  span.id = \"temp-comment-measure\";\n\n  document.body.appendChild(span);\n  const height = span.offsetHeight;\n  document.body.removeChild(span);\n\n  return height + paddingBottom;\n}\n\nexport function getTableHeight(table, width, showComments = true) {\n  return (\n    table.fields.length * tableFieldHeight +\n    tableHeaderHeight +\n    tableColorStripHeight +\n    getCommentHeight(table.comment, width, showComments)\n  );\n}\n"
  },
  {
    "path": "src/utils/validateSchema.js",
    "content": "import { Validator } from \"jsonschema\";\nimport { ddbSchema, jsonSchema } from \"../data/schemas\";\n\nexport function jsonDiagramIsValid(obj) {\n  return new Validator().validate(obj, jsonSchema).valid;\n}\n\nexport function ddbDiagramIsValid(obj) {\n  return new Validator().validate(obj, ddbSchema).valid;\n}\n"
  },
  {
    "path": "tailwind.config.js",
    "content": "/** @type {import('tailwindcss').Config} */\nexport default {\n  content: [\n    \"./src/**/*.{js,jsx,ts,tsx}\",\n  ],\n  theme: {\n    screens: {\n      '3xl': {'max': '2047px'},\n      '2xl': {'max': '1535px'},\n      'xl': {'min': '1024px'},\n      'lg': {'max': '1023px'},\n      'md': {'max': '820px'},\n      'sm': {'max': '639px'}\n    },\n    extend: {}\n  },\n  plugins: [],\n}\n\n"
  },
  {
    "path": "vercel.json",
    "content": "{\n    \"rewrites\": [\n        {\"source\": \"/(.*)\", \"destination\": \"/\"}\n    ]\n}"
  },
  {
    "path": "vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  }
]