diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f2cc2de7..41ad8b12 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -12,6 +12,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v2 + with: + fetch-depth: 0 - name: Install system dependencies run: | @@ -29,7 +31,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: '18' + node-version: '22' - name: Install dependencies run: npm install diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..08321a56 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "i18n-ally.localesPaths": ["locales"], + "i18n-ally.namespace": true, + "i18n-ally.enabledFrameworks": ["i18next"], + "i18n-ally.pathMatcher": "{locale}/{namespace}.json", + "i18n-ally.keystyle": "nested", +} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5aff0e11..5d696cd6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,61 +17,41 @@ For direct contributions, see the following guidelines. 1. Fork this repo and clone locally. If you have forked previously, sync to get the latest changes. -2. Add the JSON file in `src/webpages/gallery/` (follow the naming convention there). +2. Run `npm install` (you don't need to run build). -3. If the work contains a background image, put it also in `src/webpages/gallery/`, and edit the `.json` file to include backgroundImage": "IMAGE_FILENAME". +3. Run `npm run add-to-gallery` and follow the instructions there. 4. Commit your changes, push to your fork, and create a pull request. ## Contributing translations -You can submit a complete or partial translation for a new language, make progress to an incomplete language, or improve translation for an existing language. You don't need to understand the code to do the translation. Currently, the translation of the Gallery can only be done manually. -1. Download the target locale file: - - German: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/de.json - - Spanish: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/es.json - - French: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/fr.json - - Japanese: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/ja.json - - Korean: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/ko.json - - Dutch: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/nl.json - - Polish: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/pl.json - - Brazilian Portuguese: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/pt_BR.json - - Russian: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/ru.json - - Sinhala: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/si.json - - Traditional Chinese: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/zh_TW.json - - Simplified Chinese: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/zh_CN.json - - Template for a new language: https://raw.githubusercontent.com/ricktu288/ray-optics/master/locales/template.json - - _NOTE: If it is indicated above (or in some PR) that some update for a language has been submitted but not yet merged, please wait until it is merged to avoid repeated translation._ -2. Translate the phrase/sentence in the quotation after `"message":` to the target language. If you encounter `<` and `>`, leave the text between them untouched; `&` means the "&" symbol; `\"` means a quote, and ` ` means an extra space. If the translation of an item is completed, remove the line `"incomplete": true,`. For example, -```javascript - "welcome": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
To add an optical component, select a tool and click the blank space.
To load an example, please go to the Gallery page." - }, -``` -becomes (for Traditional Chinese) -```javascript - "welcome": { - "message": "歡迎使用「線光學模擬」
若要加入光學元件,請選擇工具並點擊空白處。
若要載入範例,請前往「作品集」頁面。" - }, - -``` -After that, you can submit the translated file with either method below: +> [!NOTE] +> There will likely be an online collaboration tool for translation in the near future. + +You can submit a complete or partial translation for a new language, make progress to an incomplete language, or improve translation for an existing language. The locale strings are in the `locales/` folder and is in the json format of i18next. Currently the best way to do the translation is to use an offline translation editor such as the i18n Ally extension for VSCode. + +For each language, there are four json files: + +- `main.json`: The strings for the homepage and the "Tools" and "View" toolbar of the simulator. +- `simulator.json`: The resto of the strings for the simulator. +- `gallery.json`: The strings for the Gallery page and of all the items in the Gallery. +- `modules.json`: The strings for the modules page, the module items, and the module tutorial page. + +The `main.json` and `simulator.json` are the most important ones, and should be translated first. + +If you already started the translation with the old json format before Dec 11, 2024, you can still submit that (which will be converted to the new format by some automatic script). But please do not start a new translation with the old format. + +You can submit the translated file with either method below: **Method 1: By e-mail** -3. Send the resulting file to ray-optics@phydemo.app. Include the name of the language and your name to appear on the [list of contributors](https://phydemo.app/ray-optics/about). +Send the resulting files to ray-optics@phydemo.app. Include the name of the language and your name to appear on the [list of contributors](https://phydemo.app/ray-optics/about). **Method 2: Via GitHub** (preferred if you use GitHub) -3. Fork this repo and clone locally. If you have forked previously, sync to get the latest changes. - -4. Save/replace the file as LOCALE_ID.json in `locales/`. -5. _(optional)_ If it is a new language, modify the locale list in `locales/sync.js`. -6. _(optional)_ Add/modify the translation of the welcome messages in `src/simulator/index.html`. -7. _(optional)_ Add/modify src/webpages/LOCALE_ID/index.html. -8. _(optional)_ Add/modify the language-related metadata and the language dropdowns of the homepages in all locales and the simulator for the new locale. -9. Commit your changes, push to your fork, and create a pull request. +1. Fork this repo and clone locally. If you have forked previously, sync to get the latest changes. +2. Save/replace the locale files. If it is a new language, just create the new folder in `locales/` with the locale ID as the name. +3. Commit your changes, push to your fork, and create a pull request. ## Contributing modules @@ -86,11 +66,9 @@ See Tools -> Others -> Import Modules for more information about modules. See [t 1. Fork this repo and clone locally. If you have forked previously, sync to get the latest changes. -2. Add the JSON file in `src/webpages/modules/` (follow the naming convention there). - -3. _(optional)_ Take a PNG screenshot for the thumbnail. +2. Run `npm install` (you don't need to run build). -4. _(optional)_ Edit `src/webpages/modules/data.json` with a text editor. This file contains the metadata for all the modules. The ID of an item is the JSON file name without the `.json`. If you replace an existing items, you can change the title but not the ID, and you should append you name in the list of contributors. +3. Run `npm run add-to-modules` and follow the instructions there. 5. Commit your changes, push to your fork, and create a pull request. diff --git a/README.md b/README.md index 14d65b8a..cee48176 100644 --- a/README.md +++ b/README.md @@ -52,37 +52,40 @@ To contribute code, you need to have some knowledge of JavaScript and module bun # Installation > [!NOTE] -> The following instructions are for developers. If you just want to use the simulator, you can launch the web app directly from [here](https://phydemo.app/ray-optics/simulator/). +> The following instructions are for those who want to install the project locally. If you just want to use the web app, you can launch it directly from [here](https://phydemo.app/ray-optics/simulator/). -To install the project locally, you need to have Node.js installed. Then, run the following commands in the terminal: +To run the web app locally, you need to have Node.js installed. Then, run the following commands in the terminal: ```bash git clone https://github.com/ricktu288/ray-optics.git cd ray-optics +npm install --no-optional +npm run start +``` +After that, the simulator web app should be running at `http://localhost:8080/simulator/`. Note however that some links and the "import module" window will not work because the other part of the project is not built. + +If you want to build the entire project, including the home pages, gallery, modules, documentation, and the node version of the simulator, you can run the following command: +```bash npm install npm run build ``` -After that, the entire content for the [https://phydemo.app/ray-optics](https://phydemo.app/ray-optics) website will be in the `dist` folder. For example, you can open the `dist/simulator/index.html` file in your browser to run the simulator. +After that, the entire content for the [https://phydemo.app/ray-optics](https://phydemo.app/ray-optics) website will be in the `dist` folder. If an error occurs during the installation, some common reasons are: - The version of Node.js is too old. You can update Node.js to version 18 or later. - Some system dependencies for node-canvas are missing. You can find the instructions for installing the dependencies in the [node-canvas repository](https://github.com/Automattic/node-canvas). -The full build may takes about half an hour to complete due to the generation of the large numbers of images for the gallery. See the following section if you only want to build the simulator. +The full build may takes about half an hour to complete due to the generation of the large numbers of images for the gallery. ## Development -For development, you don't need to build the entire website every time some code is changed. Instead, you can run the following command to start a local server: -```bash -npm run start -``` -which serves the simulator web app at `http://localhost:8080`, and is automatically reloaded when some code for the simulator is modified. However, this does not include other part of this project such as the home pages, gallery and documentation. The separate build commands are available for these pages: +For development of the web app, you can just use `npm run start`, and the web app will be automatically reloaded when some code for the simulator is modified. However, to rebuild some other part of this project, you need to run the following commands: ```bash -# build translations -npm run build-translations - -# build home pages, about pages, gallery (not including image generation), and modules pages. +# build home pages, about pages, gallery, and modules pages (not including scenes and image generation). npm run build-webpages +# build the scenes for the gallery and modules pages. +npm run build-scenes + # build the node module version of the simulator, which is required for the image generation. npm run build-node @@ -97,18 +100,14 @@ npm run build-docs ``` Note that `npm run build` is equivalent to running all the above commands. -If you add new translatable strings to `src/translations/en.json`, you can run the following command to synchronize the strings to other languages so that translators can see the new strings to translate: -```bash -npm run sync-translations -``` - ## Project structure - `src` contains the source code for the project. -- `src/simulator` contains the source code for the simulator app. To understand the structure of the code, see the [documentation](https://phydemo.app/ray-optics/docs/) for more information. The documentation is generated from the jsdoc comments in the code. +- `src/simulator` contains the source code for the simulator app, which is to be built by webpack. To understand the structure of the code, see the [documentation](https://phydemo.app/ray-optics/docs/) for more information. The documentation is generated from the jsdoc comments in the code. - `src/simulator-node` contains the source code for the node module version of the simulator. -- `src/webpages` contains the code for the home pages, about pages, templates for gallery and module pages, and the JSON files for the gallery and modules. -- `locales` contains the translations for the project. Currently it is only automatically built for the simulator app. The translations for the webpages, gallery, and modules pages are manually built. +- `src/webpages` contains the handlebars templates for the home, about, gallery and module pages, to be built by `scripts/buildWebpages.mjs`. +- `data` contains the data for gallery, modules, and the list of contributors. +- `locales` contains the translations for the project in i18next format. - `scripts` contains the scripts for custom build steps. - `dist` contains the built files for the project (the entire content for the [https://phydemo.app/ray-optics](https://phydemo.app/ray-optics) website). - `dist-node` contains the built files for the node module version of the simulator, which is required for the image generation, and can also be used in your own project. @@ -124,7 +123,7 @@ After that, you can use the simulator in your own project by importing the modul const { Scene, Simulator, sceneObjs, geometry } = require('path/to/ray-optics/dist-node/main.js'); ``` -See the [documentation](https://phydemo.app/ray-optics/docs/) for more information about the API. For a usage example, see the [image generation script](https://github.com/ricktu288/ray-optics/blob/master/scripts/buildImages.js). +See the [documentation](https://phydemo.app/ray-optics/docs/) for more information about the API. For a usage example, see the [image generation script](https://github.com/ricktu288/ray-optics/blob/master/scripts/buildImages.mjs). # License diff --git a/data/contributors.json b/data/contributors.json new file mode 100644 index 00000000..bc52871f --- /dev/null +++ b/data/contributors.json @@ -0,0 +1,371 @@ +[ + { + "name": "Yi-Ting Tu", + "isMainAuthor": true, + "githubEmails": [ + "ricktu256@gmail.com", + "ricktu256@yahoo.com.tw" + ], + "contributions": { + "code": true, + "uiDesign": true, + "gallery": true, + "modules": true, + "translations": [ + "zh-TW", + "zh-CN" + ] + }, + "firstCommit": "2016-02-22" + }, + { + "name": "Scott Cheng", + "githubEmails": [ + "chengscott@live.com" + ], + "contributions": { + "code": true + }, + "firstCommit": "2016-05-17" + }, + { + "name": "Wei-Fang Sun", + "githubEmails": [ + "j3.soon@msa.hinet.net" + ], + "contributions": { + "code": true, + "uiDesign": true + }, + "firstCommit": "2018-04-14" + }, + { + "name": "cyamahat", + "githubEmails": [ + "christophe.yamahata@gmail.com" + ], + "contributions": { + "code": true + }, + "firstCommit": "2021-02-27" + }, + { + "name": "Paul Falstad", + "githubEmails": [ + "paul@falstad.com" + ], + "contributions": { + "code": true, + "gallery": true + }, + "firstCommit": "2021-03-15" + }, + { + "name": "GLmontanari", + "githubEmails": [ + "gianlucamontanari4@gmail.com" + ], + "contributions": { + "code": true + }, + "firstCommit": "2022-08-05" + }, + { + "name": "Martin Poitras", + "contributions": { + "code": true + }, + "firstCommit": "2022-08-05" + }, + { + "name": "BoopSnoot", + "contributions": { + "translations": [ + "ru" + ] + }, + "firstCommit": "2022-10-18" + }, + { + "name": "mahjsa", + "contributions": { + "translations": [ + "nl" + ] + }, + "firstCommit": "2022-10-18" + }, + { + "name": "Wen Zhou", + "contributions": { + "gallery": true + }, + "firstCommit": "2022-10-19" + }, + { + "name": "Stas Fainer", + "githubEmails": [ + "114682673+StasFainer@users.noreply.github.com", + "stasfainer@gmail.com" + ], + "contributions": { + "code": true, + "gallery": true, + "modules": true + }, + "firstCommit": "2022-10-19" + }, + { + "name": "kqakqakqa", + "githubEmails": [ + "58761476+kqakqakqa@users.noreply.github.com" + ], + "contributions": { + "code": true, + "translations": [ + "zh-CN" + ] + }, + "firstCommit": "2022-10-26" + }, + { + "name": "Cutivel Dimitri", + "contributions": { + "translations": [ + "fr" + ] + }, + "firstCommit": "2022-10-30" + }, + { + "name": "Vincent Fan", + "contributions": { + "code": true, + "uiDesign": true, + "gallery": true + }, + "firstCommit": "2022-11-06" + }, + { + "name": "Lo-Chen Cheng", + "githubEmails": [ + "luke.cheng.725443@gmail.com" + ], + "contributions": { + "translations": [ + "de" + ] + }, + "firstCommit": "2022-12-31" + }, + { + "name": "Victory Science", + "contributions": { + "gallery": true + }, + "firstCommit": "2023-01-09" + }, + { + "name": "James Garrard", + "githubEmails": [ + "gljames24@gmail.com" + ], + "contributions": { + "code": true, + "gallery": true + }, + "firstCommit": "2023-01-13" + }, + { + "name": "Matteo Ricci Cipolloni", + "contributions": { + "gallery": true + }, + "firstCommit": "2023-02-11" + }, + { + "name": "Mikhail Kochiev", + "contributions": { + "gallery": true + }, + "firstCommit": "2023-03-04" + }, + { + "name": "Fundacja Nauka i Wiedza", + "contributions": { + "translations": [ + "pl" + ] + }, + "firstCommit": "2023-03-04" + }, + { + "name": "Michael Heise", + "githubEmails": [ + "mh.mh@web.de" + ], + "contributions": { + "translations": [ + "de" + ] + }, + "firstCommit": "2023-05-15" + }, + { + "name": "Adrian Dorrington", + "githubEmails": [ + "adrian.dorrington@gmail.com" + ], + "contributions": { + "code": true + }, + "firstCommit": "2023-05-19" + }, + { + "name": "Steve Stonebraker", + "contributions": { + "gallery": true + }, + "firstCommit": "2023-06-02" + }, + { + "name": "sadajun916", + "githubEmails": [ + "24631614+sadajun916@users.noreply.github.com" + ], + "contributions": { + "translations": [ + "ja" + ] + }, + "firstCommit": "2023-06-04" + }, + { + "name": "Tharusha Theekshana", + "githubEmails": [ + "tharushatheekshana4@gmail.com" + ], + "contributions": { + "translations": [ + "si" + ] + }, + "firstCommit": "2023-09-09" + }, + { + "name": "krzysztofkrzeslak", + "contributions": { + "uiDesign": true + }, + "firstCommit": "2023-09-16" + }, + { + "name": "Young-Gi Kim", + "contributions": { + "translations": [ + "ko" + ] + }, + "firstCommit": "2023-09-17" + }, + { + "name": "chuangyu J", + "contributions": { + "gallery": true + }, + "firstCommit": "2023-12-16" + }, + { + "name": "Miguel Sánchez Palomino", + "githubEmails": [ + "miguelsanchez1703@gmail.com" + ], + "contributions": { + "translations": [ + "es" + ] + }, + "firstCommit": "2024-01-28" + }, + { + "name": "Georg Nadorff", + "contributions": { + "gallery": true + }, + "firstCommit": "2024-02-15" + }, + { + "name": "Rene", + "contributions": { + "gallery": true + }, + "firstCommit": "2024-02-28" + }, + { + "name": "SukkaW", + "githubEmails": [ + "isukkaw@gmail.com" + ], + "contributions": { + "code": true + }, + "firstCommit": "2024-03-01" + }, + { + "name": "digitalgreenery", + "githubEmails": [ + "digitalgreenery@proton.me" + ], + "contributions": { + "code": true + }, + "firstCommit": "2024-03-18" + }, + { + "name": "Pedroobraga", + "githubEmails": [ + "peterbragacbm@gmail.com" + ], + "contributions": { + "translations": [ + "pt-BR" + ] + }, + "firstCommit": "2024-04-25" + }, + { + "name": "josephernest", + "contributions": { + "modules": true + }, + "firstCommit": "2024-07-26" + }, + { + "name": "Alex", + "contributions": { + "gallery": true + }, + "firstCommit": "2024-09-05" + }, + { + "name": "Liu Quanhong", + "contributions": { + "gallery": true + }, + "firstCommit": "2024-11-16" + }, + { + "name": "Peter Becher", + "contributions": { + "gallery": true + }, + "firstCommit": "2024-11-26" + }, + { + "name": "Mario Petitclerc", + "contributions": { + "gallery": true + }, + "firstCommit": "2024-12-03" + } +] \ No newline at end of file diff --git a/data/galleryList.json b/data/galleryList.json new file mode 100644 index 00000000..ec355483 --- /dev/null +++ b/data/galleryList.json @@ -0,0 +1,420 @@ +[ + { + "id": "reflection", + "content": [ + { + "id": "images-formed-by-two-mirrors", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "parabolic-mirror", + "contributors": [ + "Paul Falstad" + ] + }, + { + "id": "hyperbolic-mirror", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "retroreflectors", + "contributors": [ + "Stas Fainer", + "Yi-Ting Tu" + ] + }, + { + "id": "periscope", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "newtonian-telescope", + "contributors": [ + "Matteo Ricci Cipolloni" + ] + }, + { + "id": "penrose-unilluminable-room", + "contributors": [ + "Vincent Fan", + "Yi-Ting Tu" + ] + }, + { + "id": "optical-cavity", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "resonator", + "contributors": [ + "Mikhail Kochiev" + ] + }, + { + "id": "maze-solution", + "contributors": [ + "Stas Fainer", + "Yi-Ting Tu" + ] + }, + { + "id": "specular-and-diffuse-reflection", + "contributors": [ + "Steve Stonebraker" + ] + }, + { + "id": "chaff-countermeasure", + "contributors": [ + "Stas Fainer", + "Yi-Ting Tu" + ] + }, + { + "id": "caustics-from-a-reflective-sphere", + "contributors": [ + "Georg Nadorff" + ] + }, + { + "id": "the-mirascope", + "contributors": [ + "Mario Petitclerc" + ] + } + ] + }, + { + "id": "refraction", + "content": [ + { + "id": "reflect", + "contributors": [ + "Paul Falstad" + ] + }, + { + "id": "internal-reflection", + "contributors": [ + "Paul Falstad" + ] + }, + { + "id": "prisms", + "contributors": [ + "Paul Falstad" + ] + }, + { + "id": "beam-directors", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "apparent-depth", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "bended-pencil", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "broken-pencil", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "chromatic-dispersion", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "rainbows", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "minimum-deviation-angle", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "aplanatic-points", + "contributors": [ + "Stas Fainer" + ] + } + ] + }, + { + "id": "lens", + "content": [ + { + "id": "concave-lens", + "contributors": [ + "Paul Falstad" + ] + }, + { + "id": "convex-lens", + "contributors": [ + "Paul Falstad" + ] + }, + { + "id": "lens-images", + "contributors": [ + "Paul Falstad" + ] + }, + { + "id": "transverse-and-longitudinal-magnification", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "vanishing-point", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "monochromatic-aberrations", + "contributors": [ + "Paul Falstad", + "Stas Fainer" + ] + }, + { + "id": "chromatic-aberration", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "hyperbolic-lens", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "fresnel-lens", + "contributors": [ + "Stas Fainer", + "Yi-Ting Tu" + ] + } + ] + }, + { + "id": "combination-of-lenses", + "content": [ + { + "id": "zoom-lens", + "contributors": [ + "Paul Falstad" + ] + }, + { + "id": "compound-microscope", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "telescope", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "keplerian-telescope", + "contributors": [ + "chuangyu J" + ] + }, + { + "id": "beam-expanders", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "ray-relaying", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "rochester-cloak", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "simple-double-gauss-lens", + "contributors": [ + "Alex" + ] + }, + { + "id": "pair-of-axicons-making-a-rainbow-ring", + "contributors": [ + "Peter Becher" + ] + } + ] + }, + { + "id": "GRIN-optics", + "content": [ + { + "id": "GRIN-slab", + "contributors": [ + "Stas Fainer", + "Yi-Ting Tu" + ] + }, + { + "id": "inferior-mirage", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "sea-mirage", + "contributors": [ + "chuangyu J" + ] + }, + { + "id": "logarithmic-spiral-lens", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "luneburg-lens", + "contributors": [ + "Stas Fainer", + "Yi-Ting Tu" + ] + }, + { + "id": "maxwell-fisheye-lens", + "contributors": [ + "Stas Fainer", + "Yi-Ting Tu" + ] + }, + { + "id": "branched-flow", + "contributors": [ + "Yi-Ting Tu" + ] + } + ] + }, + { + "id": "miscellaneous", + "content": [ + { + "id": "single-ray-demo", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "spherical-lens-and-mirror", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "interrogation-room", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "camera-obscura", + "contributors": [ + "Stas Fainer" + ] + }, + { + "id": "the-principle-of-camera-imaging", + "contributors": [ + "Liu Quanhong" + ] + }, + { + "id": "NL-simulation", + "contributors": [ + "Wen Zhou" + ] + }, + { + "id": "einstein-ring-refocused-to-single-image-via-eyepiece", + "contributors": [ + "Jordan Anderson" + ] + }, + { + "id": "black-cat-becomes-white", + "contributors": [ + "Victory Science", + "Yi-Ting Tu" + ] + }, + { + "id": "dichroic-rbg-splitter-and-combiner", + "contributors": [ + "James Garrard" + ] + }, + { + "id": "gan-based-lcd-pixel", + "contributors": [ + "James Garrard" + ] + }, + { + "id": "concave-mirror-wearable-display", + "contributors": [ + "Rene" + ] + }, + { + "id": "reflecting-monochromator", + "contributors": [ + "James Garrard" + ] + }, + { + "id": "solar-eclipses", + "contributors": [ + "Yi-Ting Tu" + ] + } + ] + } +] \ No newline at end of file diff --git a/src/webpages/cn/gallery/GRIN-slab.json b/data/galleryScenes/GRIN-slab.json similarity index 90% rename from src/webpages/cn/gallery/GRIN-slab.json rename to data/galleryScenes/GRIN-slab.json index 718eda40..f6909e5b 100644 --- a/src/webpages/cn/gallery/GRIN-slab.json +++ b/data/galleryScenes/GRIN-slab.json @@ -149,20 +149,20 @@ "type": "TextLabel", "x": -270.0000000000001, "y": -172, - "text": "警告:光线出现的顺序并不代表实际的光速。只有最终的图像有意义。", + "text": "{{warningthesequenceof}}", "fontSize": "37" }, { "type": "TextLabel", "x": -223.99999999999997, "y": 140.1290322580645, - "text": "用多层近似的渐变折射率平板(您可以选择并更改层数 N)" + "text": "{{approximatedmultilay}}" }, { "type": "TextLabel", "x": -214.70967741935488, "y": 451.0645161290323, - "text": "正统的渐变折射率平板(您可以选择并更改数值求解器的步长)" + "text": "{{classicalgrinslabyou}}" }, { "type": "CropBox", @@ -193,6 +193,5 @@ "x": 588.1069989124172, "y": 483.9899180908078 }, - "scale": 1, - "name": "渐变折射率平板" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/pl/gallery/NL-simulation.json b/data/galleryScenes/NL-simulation.json similarity index 99% rename from src/webpages/pl/gallery/NL-simulation.json rename to data/galleryScenes/NL-simulation.json index b3bc662b..c0634df7 100644 --- a/src/webpages/pl/gallery/NL-simulation.json +++ b/data/galleryScenes/NL-simulation.json @@ -429,6 +429,5 @@ "x": 1490.7872944906921, "y": 877.8549990900746 }, - "scale": 1, - "name": "Lornetki NL" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/tw/gallery/aplanatic-points.json b/data/galleryScenes/aplanatic-points.json similarity index 86% rename from src/webpages/tw/gallery/aplanatic-points.json rename to data/galleryScenes/aplanatic-points.json index 09fbce06..3e66e4ba 100644 --- a/src/webpages/tw/gallery/aplanatic-points.json +++ b/data/galleryScenes/aplanatic-points.json @@ -223,19 +223,19 @@ "type": "TextLabel", "x": -960, "y": -480, - "text": "點選「延長光線」按鈕以驗證從球面鏡片中的光源(點 A)發出的光,\n是從球面鏡片外的光學軸上的另一點(點 B)發散,無球面像差。\n點 A 和 B 是球體的等光程點的例子。對於此點,在標記的 Y 軸的相對座標中(k1, k2, n1, n2, x1, x2, E)=(1, -1, 1.5, 1, 3 * 20, -4.5 * 20, 0),\n其中 x1,x2 是點 A,B 的水平座標(每個格線單元的尺寸為 20x20)。\n同樣地,橢圓的焦點(點 C 和 D)是橢圓的等光程點的例子,對於此點(k1, k2, n1, n2, E)=(1, 1, 1.5, 1.5, > 0)" + "text": "{{clickontheextendedra}}" }, { "type": "TextLabel", "x": 1020, "y": -60, - "text": "球面透鏡" + "text": "{{sphericallens}}" }, { "type": "TextLabel", "x": 1009.3333333333333, "y": -544, - "text": "橢圓透鏡" + "text": "{{ellipticallens}}" }, { "type": "TextLabel", @@ -265,7 +265,7 @@ "type": "TextLabel", "x": 638.1814223512337, "y": -877.7406869859694, - "text": "Y 軸", + "text": "{{yaxis}}", "alignment": "center" }, { @@ -298,6 +298,5 @@ "x": 1583.2835055896667, "y": 1523.6425564126162 }, - "scale": 1, - "name": "等光程點" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/tw/gallery/apparent-depth.json b/data/galleryScenes/apparent-depth.json similarity index 81% rename from src/webpages/tw/gallery/apparent-depth.json rename to data/galleryScenes/apparent-depth.json index cb3daedd..a137507d 100644 --- a/src/webpages/tw/gallery/apparent-depth.json +++ b/data/galleryScenes/apparent-depth.json @@ -34,29 +34,29 @@ "type": "TextLabel", "x": 714.7, "y": 537.4, - "text": "觀察到的像(橘點)" + "text": "{{observedimageorange}}" }, { "type": "TextLabel", "x": 910.7, "y": 256.4, - "text": "觀察者" + "text": "{{observer}}" }, { "type": "TextLabel", "x": 697.7, "y": 616.4, - "text": "水中物體(綠點)" + "text": "{{objectunderwatergree}}" }, { "type": "CropBox", "p1": { - "x": 385.5999999999996, - "y": 187.29999999999998 + "x": 293.90844999999985, + "y": 179.63222500000003 }, "p4": { - "x": 1422.3999999999996, - "y": 660.1600000000001 + "x": 1344.90845, + "y": 671.5450000000001 } }, { @@ -86,6 +86,5 @@ "x": -126.39999999999964, "y": 71.9 }, - "scale": 1, - "name": "視深度" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/gallery/beam-directors.json b/data/galleryScenes/beam-directors.json similarity index 92% rename from src/webpages/gallery/beam-directors.json rename to data/galleryScenes/beam-directors.json index 1afe1f30..ee709819 100644 --- a/src/webpages/gallery/beam-directors.json +++ b/data/galleryScenes/beam-directors.json @@ -113,20 +113,20 @@ "type": "TextLabel", "x": 550, "y": 496, - "text": "This fresnel biprism was made from the above biprism.\nYou can select the biprism and adjust the N_silce parameter." + "text": "{{thisfresnelbiprismwa}}" }, { "type": "TextLabel", "x": 714.5365853658536, "y": 630.5365853658537, - "text": "Fresnel biprism", + "text": "{{fresnelbiprism}}", "alignment": "right" }, { "type": "TextLabel", "x": 711.9024390243901, "y": 314.04878048780495, - "text": "Biprism", + "text": "{{biprism}}", "alignment": "right" }, { @@ -159,6 +159,5 @@ "x": -8.02499568632362, "y": 215.4517791218074 }, - "scale": 1, - "name": "Beam Directors" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/cn/gallery/beam-expanders.json b/data/galleryScenes/beam-expanders.json similarity index 92% rename from src/webpages/cn/gallery/beam-expanders.json rename to data/galleryScenes/beam-expanders.json index ec546585..cd498c15 100644 --- a/src/webpages/cn/gallery/beam-expanders.json +++ b/data/galleryScenes/beam-expanders.json @@ -1,6 +1,5 @@ { "version": 5, - "name": "扩束镜", "objs": [ { "type": "IdealLens", @@ -98,21 +97,21 @@ "type": "TextLabel", "x": 766.5714285714287, "y": 511.9999999999999, - "text": "开普勒扩束镜", + "text": "{{keplerianbeamexpande}}", "alignment": "right" }, { "type": "TextLabel", "x": 764, "y": 711.9999999999998, - "text": "伽利略扩束镜", + "text": "{{gallileanbeamexpande}}", "alignment": "right" }, { "type": "TextLabel", "x": 621.7368421052631, "y": 364, - "text": "在两种类型中,镜头之间的距离都等于它们的焦距之和" + "text": "{{inbothcasesthedistan}}" }, { "type": "CropBox", diff --git a/src/webpages/gallery/bended-pencil-background.png b/data/galleryScenes/bended-pencil-background.png similarity index 100% rename from src/webpages/gallery/bended-pencil-background.png rename to data/galleryScenes/bended-pencil-background.png diff --git a/src/webpages/gallery/bended-pencil.json b/data/galleryScenes/bended-pencil.json similarity index 91% rename from src/webpages/gallery/bended-pencil.json rename to data/galleryScenes/bended-pencil.json index 9af5e051..1a13ff06 100644 --- a/src/webpages/gallery/bended-pencil.json +++ b/data/galleryScenes/bended-pencil.json @@ -82,32 +82,32 @@ "type": "TextLabel", "x": 1022.5261689664474, "y": 501.105882042485, - "text": "bent pencil (yellow)\nimage on retina" + "text": "{{bentpencilyellowimag}}" }, { "type": "TextLabel", "x": 233.13442005815097, "y": 595.5632519114808, - "text": "dielectric material" + "text": "{{dielectricmaterial}}" }, { "type": "TextLabel", "x": 613.6954349053124, "y": 466.332582042485, - "text": "original pencil (green)" + "text": "{{originalpencilgreen}}" }, { "type": "TextLabel", "x": 813.4997485299867, "y": 701.2435132076063, - "text": "observer's eye", + "text": "{{observerseye}}", "alignment": "center" }, { "type": "TextLabel", "x": 617.8264181705608, "y": 758.3098816551066, - "text": "Ignore the orange squares!", + "text": "{{ignoretheorangesquar}}", "alignment": "center" }, { @@ -149,6 +149,5 @@ "y": 405.97089028460323 }, "scale": 1, - "name": "Bent Pencil", "backgroundImage": "bended-pencil-background.png" } \ No newline at end of file diff --git a/src/webpages/gallery/black-cat-becomes-white-background.png b/data/galleryScenes/black-cat-becomes-white-background.png similarity index 100% rename from src/webpages/gallery/black-cat-becomes-white-background.png rename to data/galleryScenes/black-cat-becomes-white-background.png diff --git a/src/webpages/cn/gallery/black-cat-becomes-white.json b/data/galleryScenes/black-cat-becomes-white.json similarity index 97% rename from src/webpages/cn/gallery/black-cat-becomes-white.json rename to data/galleryScenes/black-cat-becomes-white.json index 9fdb3dd6..0ecfdbbb 100644 --- a/src/webpages/cn/gallery/black-cat-becomes-white.json +++ b/data/galleryScenes/black-cat-becomes-white.json @@ -637,41 +637,41 @@ "type": "TextLabel", "x": 716.7777777777783, "y": -327.86666666666656, - "text": "当塑胶套在水中时,来自纸上的光无法到达眼睛,\n故我们只看到画在塑胶套上的图案。" + "text": "{{whenthebagisunderwat}}" }, { "type": "TextLabel", "x": 496.3813664596275, "y": -81.1682539682537, - "text": "来自塑胶套上的光", + "text": "{{lightfromtheplastics}}", "alignment": "center" }, { "type": "TextLabel", "x": 150.29440993788845, "y": -81.16825396825368, - "text": "来自纸上的光", + "text": "{{lightfromthepaper}}", "alignment": "center" }, { "type": "TextLabel", "x": 6.661835748792635, "y": -602.8666666666667, - "text": "眼睛", + "text": "{{eyes}}", "alignment": "right" }, { "type": "TextLabel", "x": 716.5803140096623, "y": -235.9971014492753, - "text": "拖曳此处可将塑胶套移出水面", + "text": "{{dragtomovethebagouto}}", "fontSize": 18 }, { "type": "TextLabel", "x": 350.8357487922708, "y": -602.8666666666664, - "text": "眼睛", + "text": "{{eyes}}", "alignment": "right" }, { @@ -705,6 +705,5 @@ "y": 1210.1784161490682 }, "scale": 1, - "name": "「黑猫变白猫」演示", "backgroundImage": "black-cat-becomes-white-background.png" } \ No newline at end of file diff --git a/src/webpages/tw/gallery/branched-flow.json b/data/galleryScenes/branched-flow.json similarity index 98% rename from src/webpages/tw/gallery/branched-flow.json rename to data/galleryScenes/branched-flow.json index 433f36c1..28fd452c 100644 --- a/src/webpages/tw/gallery/branched-flow.json +++ b/data/galleryScenes/branched-flow.json @@ -70,6 +70,5 @@ "x": -240.95025652484844, "y": -103.60224591966603 }, - "scale": 1, - "name": "分支流" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/gallery/broken-pencil-background.png b/data/galleryScenes/broken-pencil-background.png similarity index 100% rename from src/webpages/gallery/broken-pencil-background.png rename to data/galleryScenes/broken-pencil-background.png diff --git a/src/webpages/gallery/broken-pencil.json b/data/galleryScenes/broken-pencil.json similarity index 92% rename from src/webpages/gallery/broken-pencil.json rename to data/galleryScenes/broken-pencil.json index 7bd9e699..963195d3 100644 --- a/src/webpages/gallery/broken-pencil.json +++ b/data/galleryScenes/broken-pencil.json @@ -96,34 +96,34 @@ "type": "TextLabel", "x": 830.0100000000001, "y": 469.2399999999999, - "text": "broken pencil (yellow)\nimage on retina" + "text": "{{brokenpencilyellowim}}" }, { "type": "TextLabel", "x": 397.6456768558952, "y": 830.9351528384279, - "text": "dielectric material", + "text": "{{dielectricmaterial}}", "alignment": "center" }, { "type": "TextLabel", "x": 544.1222707423581, "y": 460, - "text": "original pencil (green)", + "text": "{{originalpencilgreen}}", "alignment": "center" }, { "type": "TextLabel", "x": 764.2126637554585, "y": 695.9000000000001, - "text": "observer's eye", + "text": "{{observerseye}}", "alignment": "center" }, { "type": "TextLabel", "x": 172.77710945203543, "y": 560.6412734187915, - "text": "Ignore the orange squares!", + "text": "{{ignoretheorangesquar}}", "alignment": "center" }, { @@ -165,6 +165,5 @@ "y": 387.6012114382306 }, "scale": 1, - "name": "Broken Pencil", "backgroundImage": "broken-pencil-background.png" } \ No newline at end of file diff --git a/src/webpages/cn/gallery/camera-obscura.json b/data/galleryScenes/camera-obscura.json similarity index 95% rename from src/webpages/cn/gallery/camera-obscura.json rename to data/galleryScenes/camera-obscura.json index f1da7244..6e1d67cd 100644 --- a/src/webpages/cn/gallery/camera-obscura.json +++ b/data/galleryScenes/camera-obscura.json @@ -120,20 +120,20 @@ "type": "TextLabel", "x": 763, "y": 676.3333333333335, - "text": "观察者" + "text": "{{observer2}}" }, { "type": "TextLabel", "x": 93.31962598804716, "y": 535.5267977636405, - "text": "外面的物体", + "text": "{{objectsoutside}}", "alignment": "right" }, { "type": "TextLabel", "x": 913.5043956043952, "y": 392.9062845651083, - "text": "黑暗的房间", + "text": "{{darkroom1}}", "alignment": "center" }, { @@ -166,6 +166,5 @@ "x": 458.1544534412956, "y": -8.005754960553588 }, - "scale": 1, - "name": "暗箱" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/cn/gallery/caustics-from-a-reflective-sphere.json b/data/galleryScenes/caustics-from-a-reflective-sphere.json similarity index 87% rename from src/webpages/cn/gallery/caustics-from-a-reflective-sphere.json rename to data/galleryScenes/caustics-from-a-reflective-sphere.json index 05aad204..a4b586a8 100644 --- a/src/webpages/cn/gallery/caustics-from-a-reflective-sphere.json +++ b/data/galleryScenes/caustics-from-a-reflective-sphere.json @@ -59,7 +59,7 @@ "type": "TextLabel", "x": 962.6440331598274, "y": 620.3560439560447, - "text": "移动点光源以观看焦散及节点\n在积分球中是如何变换的。\n改变遮光物的大小与位置,\n以及球的开口大小来观察更多效果。", + "text": "{{movethepointsourcear}}", "fontSize": 40 }, { @@ -93,6 +93,5 @@ "y": 1336.1106227106218 }, "scale": 1, - "simulateColors": true, - "name": "反射性球体的焦散" + "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/cn/gallery/chaff-countermeasure.json b/data/galleryScenes/chaff-countermeasure.json similarity index 95% rename from src/webpages/cn/gallery/chaff-countermeasure.json rename to data/galleryScenes/chaff-countermeasure.json index a65401b2..cff1b6b3 100644 --- a/src/webpages/cn/gallery/chaff-countermeasure.json +++ b/data/galleryScenes/chaff-countermeasure.json @@ -238,37 +238,37 @@ "type": "TextLabel", "x": -678.3571428571429, "y": 629.0714285714286, - "text": "飞机" + "text": "{{plane}}" }, { "type": "TextLabel", "x": -506, "y": 138, - "text": "雷达" + "text": "{{radar}}" }, { "type": "TextLabel", "x": 1701.642857142857, "y": 629.0714285714286, - "text": "飞机" + "text": "{{plane}}" }, { "type": "TextLabel", "x": -2896, "y": 138, - "text": "雷达" + "text": "{{radar}}" }, { "type": "TextLabel", "x": 645, "y": 857.4999999999999, - "text": "箔片" + "text": "{{chaff}}" }, { "type": "TextLabel", "x": -431, "y": 1319, - "text": "选择箔片可改变箔片数量(N)和长度(L)。", + "text": "{{selectthechafftochan}}", "fontSize": 48 }, { @@ -302,6 +302,5 @@ "y": 599.352086802087 }, "scale": 1, - "randomSeed": "0", - "name": "干扰箔" + "randomSeed": "0" } \ No newline at end of file diff --git a/src/webpages/cn/gallery/chromatic-aberration.json b/data/galleryScenes/chromatic-aberration.json similarity index 99% rename from src/webpages/cn/gallery/chromatic-aberration.json rename to data/galleryScenes/chromatic-aberration.json index 28a6ef93..def2cdcf 100644 --- a/src/webpages/cn/gallery/chromatic-aberration.json +++ b/data/galleryScenes/chromatic-aberration.json @@ -518,7 +518,7 @@ "type": "TextLabel", "x": 97.70452880452885, "y": 544.514119214119, - "text": "拖拽此处可调整光束宽度", + "text": "{{dragtoadjustbeamwidt1}}", "fontSize": 16, "alignment": "center" }, @@ -553,6 +553,5 @@ "y": -23.219787951985495 }, "scale": 1, - "simulateColors": true, - "name": "色像差" + "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/tw/gallery/chromatic-dispersion.json b/data/galleryScenes/chromatic-dispersion.json similarity index 98% rename from src/webpages/tw/gallery/chromatic-dispersion.json rename to data/galleryScenes/chromatic-dispersion.json index f66ff734..d609346d 100644 --- a/src/webpages/tw/gallery/chromatic-dispersion.json +++ b/data/galleryScenes/chromatic-dispersion.json @@ -317,14 +317,14 @@ "type": "TextLabel", "x": 419.47561821366054, "y": 343.8461116752542, - "text": "拖曳此處\n可調整光束寬度", + "text": "{{dragheretoadjustbeam}}", "fontSize": 12 }, { "type": "TextLabel", "x": 504.9456926915665, "y": 502.1990798526488, - "text": "拖曳此處\n可旋轉棱鏡", + "text": "{{dragheretorotatethep}}", "fontSize": 12, "alignment": "right" }, @@ -359,6 +359,5 @@ "y": -151.61587092073935 }, "scale": 1, - "simulateColors": true, - "name": "色散" + "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/cn/gallery/compound-microscope.json b/data/galleryScenes/compound-microscope.json similarity index 87% rename from src/webpages/cn/gallery/compound-microscope.json rename to data/galleryScenes/compound-microscope.json index 3032b8b3..ffa59687 100644 --- a/src/webpages/cn/gallery/compound-microscope.json +++ b/data/galleryScenes/compound-microscope.json @@ -51,25 +51,25 @@ "type": "TextLabel", "x": 464.3216604345087, "y": 433.32548572858167, - "text": "物镜", + "text": "{{objective}}", "alignment": "center" }, { "type": "TextLabel", "x": 847.2168985297469, "y": 516.2588190619147, - "text": "目镜", + "text": "{{eyepiece}}", "alignment": "center" }, { "type": "CropBox", "p1": { - "x": 262.42202673487486, - "y": 145.9518593549552 + "x": 222.57729596564377, + "y": 129.03670550880133 }, "p4": { - "x": 1165.745103657952, - "y": 555.7980132011091 + "x": 1184.5772959656438, + "y": 579.1744747395705 } }, { @@ -92,6 +92,5 @@ "x": -36.591257504105556, "y": 79.87890987581412 }, - "scale": 1, - "name": "复式显微镜" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/tw/gallery/concave-lens.json b/data/galleryScenes/concave-lens.json similarity index 97% rename from src/webpages/tw/gallery/concave-lens.json rename to data/galleryScenes/concave-lens.json index ef758c65..e3885686 100644 --- a/src/webpages/tw/gallery/concave-lens.json +++ b/data/galleryScenes/concave-lens.json @@ -79,6 +79,5 @@ "x": 1430.1643243369017, "y": 658.5192683356722 }, - "scale": 1, - "name": "凹透鏡" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/tw/gallery/concave-mirror-wearable-display.json b/data/galleryScenes/concave-mirror-wearable-display.json similarity index 95% rename from src/webpages/tw/gallery/concave-mirror-wearable-display.json rename to data/galleryScenes/concave-mirror-wearable-display.json index d684e6fb..b6a768cc 100644 --- a/src/webpages/tw/gallery/concave-mirror-wearable-display.json +++ b/data/galleryScenes/concave-mirror-wearable-display.json @@ -184,7 +184,7 @@ "type": "TextLabel", "x": 420.09540902027635, "y": 118.16309801309795, - "text": "TFT 0.9吋顯示器", + "text": "{{tft09display}}", "fontSize": 12, "font": "Arial", "alignment": "right" @@ -193,7 +193,7 @@ "type": "TextLabel", "x": 727.6318965348369, "y": 134.83842268842255, - "text": "凹面鏡", + "text": "{{concavemirror}}", "fontSize": 12, "font": "Arial" }, @@ -201,7 +201,7 @@ "type": "TextLabel", "x": 489.06840447134493, "y": 363.0447718947717, - "text": "眼睛", + "text": "{{eye1}}", "fontSize": 12, "font": "Arial", "alignment": "right" @@ -210,7 +210,7 @@ "type": "TextLabel", "x": 510.6240155269562, "y": 482.33720168720185, - "text": "鼻子", + "text": "{{nose}}", "fontSize": 12, "font": "Arial" }, @@ -218,7 +218,7 @@ "type": "TextLabel", "x": -1.2229345031940397, "y": 414.68122842070215, - "text": "用來測量半徑的點光源", + "text": "{{pointsourcetomeasure}}", "fontSize": 12, "font": "Arial", "alignment": "right" @@ -227,7 +227,7 @@ "type": "TextLabel", "x": 612.2657106739144, "y": 296.0621808016546, - "text": "+1.5度閱讀眼鏡", + "text": "{{t15readingglasses}}", "fontSize": 12, "font": "Arial" }, @@ -269,6 +269,5 @@ "y": 306.68582188582076 }, "scale": 1, - "simulateColors": true, - "name": "凹面鏡可穿戴顯示器" + "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/cn/gallery/convex-lens.json b/data/galleryScenes/convex-lens.json similarity index 98% rename from src/webpages/cn/gallery/convex-lens.json rename to data/galleryScenes/convex-lens.json index 3e8b1fbc..6f119bb1 100644 --- a/src/webpages/cn/gallery/convex-lens.json +++ b/data/galleryScenes/convex-lens.json @@ -1,6 +1,5 @@ { "version": 5, - "name": "凸透镜", "objs": [ { "type": "SphericalLens", diff --git a/src/webpages/tw/gallery/dichroic-rbg-splitter-and-combiner.json b/data/galleryScenes/dichroic-rbg-splitter-and-combiner.json similarity index 93% rename from src/webpages/tw/gallery/dichroic-rbg-splitter-and-combiner.json rename to data/galleryScenes/dichroic-rbg-splitter-and-combiner.json index 6d9362ef..288c4e10 100644 --- a/src/webpages/tw/gallery/dichroic-rbg-splitter-and-combiner.json +++ b/data/galleryScenes/dichroic-rbg-splitter-and-combiner.json @@ -148,27 +148,27 @@ "type": "TextLabel", "x": 436.57142857142844, "y": 352.00000000000006, - "text": "RGB分量分光器與合光器" + "text": "{{rgbcomponentsplitter}}" }, { "type": "TextLabel", "x": 588.0000000000002, "y": 469.7142857142858, - "text": "光源", + "text": "{{lightsource}}", "alignment": "right" }, { "type": "TextLabel", "x": 679.4285714285716, "y": 436, - "text": "二色性立方體", + "text": "{{dichroiccube}}", "alignment": "center" }, { "type": "TextLabel", "x": 969.142857142857, "y": 433.14285714285717, - "text": "合光器" + "text": "{{beamcombiner}}" }, { "type": "CropBox", @@ -201,6 +201,5 @@ "y": 22.914285714285768 }, "scale": 1, - "simulateColors": true, - "name": "二色性RGB分光器與合光器" + "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/gallery/einstein-ring-refocused-to-single-image-via-eyepiece.json b/data/galleryScenes/einstein-ring-refocused-to-single-image-via-eyepiece.json similarity index 98% rename from src/webpages/gallery/einstein-ring-refocused-to-single-image-via-eyepiece.json rename to data/galleryScenes/einstein-ring-refocused-to-single-image-via-eyepiece.json index 288f7556..187a909f 100644 --- a/src/webpages/gallery/einstein-ring-refocused-to-single-image-via-eyepiece.json +++ b/data/galleryScenes/einstein-ring-refocused-to-single-image-via-eyepiece.json @@ -281,6 +281,5 @@ "y": -188.03687726502045 }, "scale": 1, - "simulateColors": true, - "name": "Einstein Ring refocused to Single Image via Eyepiece" + "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/gallery/fresnel-lens.json b/data/galleryScenes/fresnel-lens.json similarity index 93% rename from src/webpages/gallery/fresnel-lens.json rename to data/galleryScenes/fresnel-lens.json index 45855ce7..ac13856b 100644 --- a/src/webpages/gallery/fresnel-lens.json +++ b/data/galleryScenes/fresnel-lens.json @@ -1,6 +1,5 @@ { "version": 5, - "name": "Fresnel lens", "modules": { "FresnelLens": { "numPoints": 2, @@ -103,7 +102,7 @@ "type": "TextLabel", "x": 1354.6447437999493, "y": 497.8676902426197, - "text": "This Fresnel lens is made from the half circle glass below.\nYou can select the lens and adjust the N_silce parameter.", + "text": "{{thisfresnellensismad}}", "alignment": "center" }, { diff --git a/src/webpages/tw/gallery/gan-based-lcd-pixel.json b/data/galleryScenes/gan-based-lcd-pixel.json similarity index 91% rename from src/webpages/tw/gallery/gan-based-lcd-pixel.json rename to data/galleryScenes/gan-based-lcd-pixel.json index 35217e57..ae2dcee0 100644 --- a/src/webpages/tw/gallery/gan-based-lcd-pixel.json +++ b/data/galleryScenes/gan-based-lcd-pixel.json @@ -204,53 +204,53 @@ "type": "TextLabel", "x": 844, "y": 486.00000000000006, - "text": "由於像素非常小,光\n在我們的眼中看起來是混合的" + "text": "{{pixelsaresosmallthel}}" }, { "type": "TextLabel", "x": 384, "y": 748, - "text": "改變透光率\n來產生任何RGB值" + "text": "{{changetherateoftrans}}" }, { "type": "TextLabel", "x": 7.684234851661699, "y": 562.0760260946291, - "text": "藍色LED背光", + "text": "{{blueledbacklight}}", "alignment": "right" }, { "type": "TextLabel", "x": 136.09942466453506, "y": 391.6666666666665, - "text": "黃色磷光體", + "text": "{{yellowphosphor}}", "alignment": "center" }, { "type": "TextLabel", "x": 455.46592181428963, "y": 387.5968253968253, - "text": "液晶", + "text": "{{liquidcrystal}}", "alignment": "center" }, { "type": "TextLabel", "x": 256.18714234109103, "y": 746.5333333333335, - "text": "濾光器", + "text": "{{lightfilters}}", "alignment": "center" }, { "type": "TextLabel", "x": 20, "y": 230.00000000000006, - "text": "觀察者看到的像素" + "text": "{{pixelasvisibletoview}}" }, { "type": "TextLabel", "x": 846, "y": 432.00000000000006, - "text": "不是液晶顯示器的一部分" + "text": "{{notpartoflcddisplay}}" }, { "type": "CropBox", @@ -283,6 +283,5 @@ "y": 238.1250859986243 }, "scale": 1, - "simulateColors": true, - "name": "液晶螢幕像素" + "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/tw/gallery/hyperbolic-lens.json b/data/galleryScenes/hyperbolic-lens.json similarity index 81% rename from src/webpages/tw/gallery/hyperbolic-lens.json rename to data/galleryScenes/hyperbolic-lens.json index 5fc9b331..f1e1edda 100644 --- a/src/webpages/tw/gallery/hyperbolic-lens.json +++ b/data/galleryScenes/hyperbolic-lens.json @@ -118,19 +118,19 @@ "type": "TextLabel", "x": -540.422222222222, "y": -143.4476190476192, - "text": "此球面透鏡的焦距(在近軸近似中)為:\nf=R/(n-1)=200/(1.5-1)=400" + "text": "{{thefocallengthofthis}}" }, { "type": "TextLabel", "x": 1117.5997557997562, "y": -184.98608058608073, - "text": "此雙曲透鏡的焦距是:\nf = |C| ∙ sqrt(n^2 - 1) / (n - 1) = K ∙ sqrt(0.8) ∙ sqrt(1.5^2 - 1) / (1.5 - 1) = 400\n此雙曲透鏡的方程式是:\ny(x) = (a/K) - sqrt( ((x/K)^2 + (C/K)^2) / (n^2 - 1) )\n= 1.5 - sqrt( (0.8 + (x / 200)^2) / (1.5^2 - 1) )\n使得K是方程式維度與網格維度之間的轉換常數 - 對於這個雙曲面鏡,K=20\n(例如05", + "type": "TextLabel", + "x": 600, + "y": 250, + "text": "{{thistextisshownonlyw}}" + }, + { + "for": [ + "i=-10:1:10", + "j=-10:1:10" + ], + "if": "i^2+j^2<11^2", + "type": "TextLabel", + "x": "`1100+25i`", + "y": "`550+25j`", + "text": "`i`,`j`", + "fontSize": 9, + "alignment": "center" + } + ] + } + }, + "objs": [ + { + "type": "ModuleObj", + "module": "ExampleModule", + "points": [], + "params": { + "n": 10, + "theta": 1.23 + } + } + ], + "width": 1200, + "height": 400, + "origin": { + "x": 298.0105908080373, + "y": 19.812605130125487 + }, + "scale": 0.45976518247654025 +} \ No newline at end of file diff --git a/data/galleryScenes/module-example-basics.json b/data/galleryScenes/module-example-basics.json new file mode 100644 index 00000000..b7e5bb08 --- /dev/null +++ b/data/galleryScenes/module-example-basics.json @@ -0,0 +1,50 @@ +{ + "version": 5, + "modules": { + "ExampleModule": { + "numPoints": 0, + "params": [], + "objs": [ + { + "type": "TextLabel", + "x": 600, + "y": 450, + "text": "{{thistextisinexamplem}}" + }, + { + "type": "TextLabel", + "x": 600, + "y": 500, + "text": "{{thistextisalsoinexam}}" + } + ] + } + }, + "objs": [ + { + "type": "TextLabel", + "x": 600, + "y": 300, + "text": "{{thistextisnotinamodu}}" + }, + { + "type": "TextLabel", + "x": 600, + "y": 350, + "text": "{{thistextisalsonotina}}" + }, + { + "type": "ModuleObj", + "module": "ExampleModule", + "points": [], + "params": {} + } + ], + "width": 1000, + "height": 400, + "origin": { + "x": 50.64898989898987, + "y": -86.41666666666666 + }, + "scale": 0.7175925925925926 +} \ No newline at end of file diff --git a/data/galleryScenes/module-example-control-points.json b/data/galleryScenes/module-example-control-points.json new file mode 100644 index 00000000..a3fe886c --- /dev/null +++ b/data/galleryScenes/module-example-control-points.json @@ -0,0 +1,53 @@ +{ + "version": 5, + "modules": { + "ExampleModule": { + "numPoints": 2, + "params": [], + "objs": [ + { + "type": "TextLabel", + "x": "`x_1`", + "y": "`y_1`", + "text": "{{hereisthefirstdragga}}" + }, + { + "type": "TextLabel", + "x": "`x_2`", + "y": "`y_2`", + "text": "{{hereistheseconddragg}}" + }, + { + "type": "TextLabel", + "x": "`(x_1+x_2)/2`", + "y": "`(y_1+y_2)/2`", + "text": "{{hereisthemidpoint}}" + } + ] + } + }, + "objs": [ + { + "type": "ModuleObj", + "module": "ExampleModule", + "points": [ + { + "x": 500, + "y": 300 + }, + { + "x": 600, + "y": 600 + } + ], + "params": {} + } + ], + "width": 1200, + "height": 400, + "origin": { + "x": 140.37500000000014, + "y": -57.249999999999986 + }, + "scale": 0.6944444444444444 +} \ No newline at end of file diff --git a/data/galleryScenes/module-example-custom-equation.json b/data/galleryScenes/module-example-custom-equation.json new file mode 100644 index 00000000..fce1382c --- /dev/null +++ b/data/galleryScenes/module-example-custom-equation.json @@ -0,0 +1,51 @@ +{ + "version": 5, + "modules": { + "ExampleModule": { + "numPoints": 0, + "params": [ + "phi=0:0.01:2pi:1" + ], + "objs": [ + { + "type": "CustomMirror", + "p1": { + "x": 600, + "y": 400 + }, + "p2": { + "x": 800, + "y": 400 + }, + "eqn": "\\cos(2 \\pi x+`phi`)" + }, + { + "type": "TextLabel", + "x": 520, + "y": 270, + "text": "{{amirrorofshapeycos2p}}" + } + ] + } + }, + "objs": [ + { + "type": "ModuleObj", + "module": "ExampleModule", + "points": [], + "params": { + "n": 2, + "theta": 1.23, + "a": 5, + "phi": 1.23 + } + } + ], + "width": 1200, + "height": 400, + "origin": { + "x": 236.49999999999994, + "y": -9.81249999999998 + }, + "scale": 0.6944444444444444 +} \ No newline at end of file diff --git a/data/galleryScenes/module-example-parameters.json b/data/galleryScenes/module-example-parameters.json new file mode 100644 index 00000000..ee1cdcce --- /dev/null +++ b/data/galleryScenes/module-example-parameters.json @@ -0,0 +1,45 @@ +{ + "version": 5, + "modules": { + "ExampleModule": { + "numPoints": 0, + "params": [ + "n=1:1:10:1", + "theta=0:0.01:5*pi:0" + ], + "objs": [ + { + "type": "TextLabel", + "x": 600, + "y": 400, + "text": "{{thismodulehastwopara}}" + }, + { + "type": "TextLabel", + "x": 600, + "y": 550, + "text": "{{thesizeofthistextosc}}", + "fontSize": "`24+3*cos(theta)`" + } + ] + } + }, + "objs": [ + { + "type": "ModuleObj", + "module": "ExampleModule", + "points": [], + "params": { + "n": 1, + "theta": 1.23 + } + } + ], + "width": 1000, + "height": 400, + "origin": { + "x": 92.44791666666666, + "y": -68.02083333333334 + }, + "scale": 0.5787037037037037 +} \ No newline at end of file diff --git a/data/galleryScenes/module-example-shape-parametrization.json b/data/galleryScenes/module-example-shape-parametrization.json new file mode 100644 index 00000000..4a395580 --- /dev/null +++ b/data/galleryScenes/module-example-shape-parametrization.json @@ -0,0 +1,74 @@ +{ + "version": 5, + "modules": { + "ExampleModule": { + "numPoints": 0, + "params": [], + "objs": [ + { + "type": "SphericalLens", + "defBy": "DFfdBfd", + "p1": { + "x": 600, + "y": 200 + }, + "p2": { + "x": 600, + "y": 350 + }, + "params": { + "d": 40, + "ffd": 300, + "bfd": 350 + }, + "refIndex": 1.5 + }, + { + "type": "SphericalLens", + "defBy": "DR1R2", + "p1": { + "x": 600, + "y": 400 + }, + "p2": { + "x": 600, + "y": 550 + }, + "params": { + "d": 40, + "r1": 300, + "r2": -350 + }, + "refIndex": 1.5 + } + ] + } + }, + "objs": [ + { + "type": "ModuleObj", + "module": "ExampleModule", + "points": [], + "params": {} + }, + { + "type": "TextLabel", + "x": 640, + "y": 480, + "text": "{{alensdefinedbydr1r2}}" + }, + { + "type": "TextLabel", + "x": 640, + "y": 280, + "text": "{{alensdefinedbydffdbf}}" + } + ], + "width": 1200, + "height": 400, + "origin": { + "x": 207.06249999999997, + "y": -9.937500000000002 + }, + "scale": 0.6944444444444444 +} \ No newline at end of file diff --git a/src/webpages/pl/gallery/monochromatic-aberrations.json b/data/galleryScenes/monochromatic-aberrations.json similarity index 96% rename from src/webpages/pl/gallery/monochromatic-aberrations.json rename to data/galleryScenes/monochromatic-aberrations.json index 7d2708b1..ecba6fd8 100644 --- a/src/webpages/pl/gallery/monochromatic-aberrations.json +++ b/data/galleryScenes/monochromatic-aberrations.json @@ -323,42 +323,42 @@ "type": "TextLabel", "x": 1120.381818181818, "y": 113.25454545454568, - "text": "Rozogniskowanie", + "text": "{{defocusaberration}}", "alignment": "center" }, { "type": "TextLabel", "x": -281.61818181818194, "y": 113.25454545454568, - "text": "Aberracja sferyczna", + "text": "{{sphericalaberration}}", "alignment": "center" }, { "type": "TextLabel", "x": 660.2194751485076, "y": 1072.237634408602, - "text": "Ekran", + "text": "{{screen}}", "alignment": "right" }, { "type": "TextLabel", "x": 1347.2, "y": 479.20000000000005, - "text": "Ekran", + "text": "{{screen}}", "alignment": "right" }, { "type": "TextLabel", "x": 420.38181818181806, "y": 753.2545454545457, - "text": "Krzywizna pola", + "text": "{{fieldcurvatureaberra}}", "alignment": "center" }, { "type": "TextLabel", "x": 426.38181818181806, "y": 113.25454545454568, - "text": "Koma", + "text": "{{commaaberration}}", "alignment": "center" }, { @@ -391,6 +391,5 @@ "x": 1595.4443349753697, "y": 687.168472906404 }, - "scale": 1, - "name": "Aberracje monochromatyczne" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/cn/gallery/newtonian-telescope.json b/data/galleryScenes/newtonian-telescope.json similarity index 99% rename from src/webpages/cn/gallery/newtonian-telescope.json rename to data/galleryScenes/newtonian-telescope.json index ebf49972..acf3777d 100644 --- a/src/webpages/cn/gallery/newtonian-telescope.json +++ b/data/galleryScenes/newtonian-telescope.json @@ -554,6 +554,5 @@ "x": 349.04334554334525, "y": 619.3345410145412 }, - "scale": 1, - "name": "牛顿望远镜" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/cn/gallery/optical-cavity.json b/data/galleryScenes/optical-cavity.json similarity index 95% rename from src/webpages/cn/gallery/optical-cavity.json rename to data/galleryScenes/optical-cavity.json index b6552e53..531f27fa 100644 --- a/src/webpages/cn/gallery/optical-cavity.json +++ b/data/galleryScenes/optical-cavity.json @@ -265,13 +265,13 @@ "type": "TextLabel", "x": 200, "y": 420, - "text": "点击 + 按住左键\n以移动光线" + "text": "{{clickholdleftmouseto}}" }, { "type": "TextLabel", "x": 977.5854137442425, "y": 1049.2819534933333, - "text": "拖曳此处\n可水平移动镜子", + "text": "{{dragtomovetheidealmi}}", "fontSize": 18, "alignment": "center" }, @@ -279,7 +279,7 @@ "type": "TextLabel", "x": 1181.8181818181815, "y": 18.181818181818016, - "text": "下方的共振腔中d = 400", + "text": "{{d400intheresonatorsb}}", "alignment": "center" }, { @@ -314,21 +314,21 @@ "type": "TextLabel", "x": -17.50146627566002, "y": 270.909090909091, - "text": "焦聚共振腔", + "text": "{{confocalresonator}}", "alignment": "center" }, { "type": "TextLabel", "x": 776.739002932551, "y": 230.90909090909096, - "text": "共心共振腔", + "text": "{{concentricresonator}}", "alignment": "center" }, { "type": "TextLabel", "x": 2379.1608391608393, "y": 230.90909090909088, - "text": "凹凸共振腔", + "text": "{{concaveconvexresonat}}", "alignment": "center" }, { @@ -363,7 +363,7 @@ "type": "TextLabel", "x": 1618.9930069930074, "y": 230.90909090909093, - "text": "平凹共振腔", + "text": "{{planoconcaveresonato}}", "alignment": "center" }, { @@ -397,6 +397,5 @@ "x": 1120.8391608391605, "y": 842.6993006993009 }, - "scale": 1, - "name": "双镜共振腔" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/tw/gallery/pair-of-axicons-making-a-rainbow-ring.json b/data/galleryScenes/pair-of-axicons-making-a-rainbow-ring.json similarity index 96% rename from src/webpages/tw/gallery/pair-of-axicons-making-a-rainbow-ring.json rename to data/galleryScenes/pair-of-axicons-making-a-rainbow-ring.json index 3d3f04f6..35ea5bbd 100644 --- a/src/webpages/tw/gallery/pair-of-axicons-making-a-rainbow-ring.json +++ b/data/galleryScenes/pair-of-axicons-making-a-rainbow-ring.json @@ -1,5 +1,4 @@ { - "name": "一對錐透鏡產生彩虹環", "version": 5, "objs": [ { @@ -425,14 +424,14 @@ "type": "TextLabel", "x": 82.61986504689585, "y": -5.809756086281965, - "text": "左側錐透鏡", + "text": "{{leftaxicon}}", "fontSize": 8 }, { "type": "TextLabel", "x": -1.2729920959612961, "y": -2.809756086281965, - "text": "白光\n光源", + "text": "{{whitelightsource}}", "fontSize": 8, "alignment": "right" }, @@ -440,7 +439,7 @@ "type": "TextLabel", "x": 218.9412936183244, "y": -6.059756086281967, - "text": "右側錐透鏡", + "text": "{{rightaxicon}}", "fontSize": 8, "alignment": "right" }, @@ -448,18 +447,18 @@ "type": "TextLabel", "x": 61.86986504689585, "y": 88.19024391371806, - "text": "環狀光圈", + "text": "{{ringaperture}}", "fontSize": 8 } ], - "width": 684.4925549092117, - "height": 399.2104169980598, + "width": 1300, + "height": 800, "rayModeDensity": 1, "gridSize": 10, "origin": { - "x": 224.10667937749974, - "y": 167.63044993900314 + "x": 498.3958859367946, + "y": 333.7448162406214 }, - "scale": 1, + "scale": 1.3092485626891148, "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/tw/gallery/parabolic-mirror.json b/data/galleryScenes/parabolic-mirror.json similarity index 97% rename from src/webpages/tw/gallery/parabolic-mirror.json rename to data/galleryScenes/parabolic-mirror.json index de289894..dcd097e4 100644 --- a/src/webpages/tw/gallery/parabolic-mirror.json +++ b/data/galleryScenes/parabolic-mirror.json @@ -87,6 +87,5 @@ "x": 661.8539734128217, "y": 104.48324170181644 }, - "scale": 1, - "name": "拋物面鏡" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/gallery/penrose-unilluminable-room.json b/data/galleryScenes/penrose-unilluminable-room.json similarity index 94% rename from src/webpages/gallery/penrose-unilluminable-room.json rename to data/galleryScenes/penrose-unilluminable-room.json index c41ab7a4..4174cec8 100644 --- a/src/webpages/gallery/penrose-unilluminable-room.json +++ b/data/galleryScenes/penrose-unilluminable-room.json @@ -197,7 +197,7 @@ "type": "TextLabel", "x": 1127.022222222223, "y": 105.84444444444438, - "text": "No matter where you put the point source, it will not shine the entire room.\nWarning: Due to numerical error, it may still shine after some time.", + "text": "{{nomatterwhereyouputt}}", "alignment": "center" }, { @@ -231,6 +231,5 @@ "x": 409.235353535353, "y": 482.42707070707047 }, - "scale": 1, - "name": "Penrose unilluminable room" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/pl/gallery/periscope.json b/data/galleryScenes/periscope.json similarity index 96% rename from src/webpages/pl/gallery/periscope.json rename to data/galleryScenes/periscope.json index 2648fa3c..72de6643 100644 --- a/src/webpages/pl/gallery/periscope.json +++ b/data/galleryScenes/periscope.json @@ -148,7 +148,7 @@ "type": "TextLabel", "x": 979.2571428571429, "y": 962.2571428571428, - "text": "Oko obserwatora (nie w skali)", + "text": "{{observerseyenottosca}}", "alignment": "center" }, { @@ -182,6 +182,5 @@ "y": 4.1428571428570535 }, "scale": 1, - "simulateColors": true, - "name": "Peryskop" + "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/cn/gallery/prisms.json b/data/galleryScenes/prisms.json similarity index 96% rename from src/webpages/cn/gallery/prisms.json rename to data/galleryScenes/prisms.json index 0b9a9fe1..654ae802 100644 --- a/src/webpages/cn/gallery/prisms.json +++ b/data/galleryScenes/prisms.json @@ -195,34 +195,34 @@ "type": "TextLabel", "x": 881.2010657279563, "y": 455.37777777777796, - "text": "菱形", + "text": "{{rhomboid}}", "alignment": "right" }, { "type": "TextLabel", "x": 125.93333333333354, "y": 683.7111111111112, - "text": "直角" + "text": "{{rightangle}}" }, { "type": "TextLabel", "x": 540.4155199286618, "y": 465.99589160387313, - "text": "波罗", + "text": "{{porro}}", "alignment": "center" }, { "type": "TextLabel", "x": 182.3182219815275, "y": 914.7111111111111, - "text": "杜福", + "text": "{{dove}}", "alignment": "center" }, { "type": "TextLabel", "x": 534.9816224388505, "y": 911.7172702972307, - "text": "五面" + "text": "{{pentaprism}}" }, { "type": "CropBox", @@ -253,6 +253,5 @@ "x": 393.9398254803017, "y": -7.727697778215429 }, - "scale": 1, - "name": "稜鏡" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/tw/gallery/rainbows.json b/data/galleryScenes/rainbows.json similarity index 91% rename from src/webpages/tw/gallery/rainbows.json rename to data/galleryScenes/rainbows.json index d3f3a8ef..1daac10c 100644 --- a/src/webpages/tw/gallery/rainbows.json +++ b/data/galleryScenes/rainbows.json @@ -157,39 +157,39 @@ "type": "TextLabel", "x": 220.53333333333342, "y": 870.1523809523809, - "text": "以上是由單個雨滴產生的顏色。\n我們最終看到的彩虹是由天空中大量的雨滴產生的,\n每個都對觀察者呈現單一一種顏色(在相應的角度)。" + "text": "{{thesearethecolorspro}}" }, { "type": "TextLabel", "x": 290.8188289789092, "y": 776.7034138036452, - "text": "霓" + "text": "{{secondaryrainbow}}" }, { "type": "TextLabel", "x": 115.7714285714286, "y": 817.1428571428569, - "text": "亞歷山大暗帶" + "text": "{{alexandersdarkband}}" }, { "type": "TextLabel", "x": 639.8285714285715, "y": 379.2571428571425, - "text": "雨滴", + "text": "{{raindrop}}", "alignment": "center" }, { "type": "TextLabel", "x": 164.97100000000012, "y": 644.3428571428567, - "text": "虹", + "text": "{{primaryrainbow}}", "alignment": "center" }, { "type": "TextLabel", "x": 87.82857142857156, "y": 342.0571428571426, - "text": "陽光" + "text": "{{sunlight}}" }, { "type": "CropBox", @@ -229,6 +229,5 @@ "y": 124.59658619635479 }, "scale": 1, - "simulateColors": true, - "name": "彩虹" + "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/cn/gallery/ray-relaying.json b/data/galleryScenes/ray-relaying.json similarity index 95% rename from src/webpages/cn/gallery/ray-relaying.json rename to data/galleryScenes/ray-relaying.json index 41977a69..f1472a7c 100644 --- a/src/webpages/cn/gallery/ray-relaying.json +++ b/data/galleryScenes/ray-relaying.json @@ -1,6 +1,5 @@ { "version": 5, - "name": "光线中继", "modules": { "RayRelay": { "numPoints": 2, @@ -102,7 +101,7 @@ "type": "TextLabel", "x": 250.47756948933397, "y": 1644.0472096530923, - "text": "您可以选择任何透镜以查看和调整阵列的参数。", + "text": "{{youcanselectanylenst}}", "fontSize": 50 }, { diff --git a/src/webpages/cn/gallery/reflect.json b/data/galleryScenes/reflect.json similarity index 96% rename from src/webpages/cn/gallery/reflect.json rename to data/galleryScenes/reflect.json index 1bf2155d..cf282bec 100644 --- a/src/webpages/cn/gallery/reflect.json +++ b/data/galleryScenes/reflect.json @@ -58,6 +58,5 @@ "x": 188.22072795107334, "y": -31.965409691137864 }, - "scale": 1, - "name": "反射与折射" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/tw/gallery/reflecting-monochromator.json b/data/galleryScenes/reflecting-monochromator.json similarity index 96% rename from src/webpages/tw/gallery/reflecting-monochromator.json rename to data/galleryScenes/reflecting-monochromator.json index 64ce8410..5b067c1a 100644 --- a/src/webpages/tw/gallery/reflecting-monochromator.json +++ b/data/galleryScenes/reflecting-monochromator.json @@ -1,6 +1,5 @@ { "version": 5, - "name": "反射式單色儀", "objs": [ { "type": "DiffractionGrating", @@ -262,21 +261,21 @@ "type": "TextLabel", "x": 422.63028885046424, "y": 368.8867243867245, - "text": "反射式單色儀", + "text": "{{reflectingmonochroma}}", "alignment": "center" }, { "type": "TextLabel", "x": 353.2183713067841, "y": 589.0268650509676, - "text": "旋轉繞射光柵\n以從多波長混合的光\n之中取得窄頻寬的光", + "text": "{{rotatediffractiongra}}", "fontSize": 12 }, { "type": "TextLabel", "x": 559.8474148820138, "y": 488.01320832883624, - "text": "出射口\n\n單色光", + "text": "{{exitslitmonochromati}}", "fontSize": 12 }, { diff --git a/src/webpages/cn/gallery/resonator.json b/data/galleryScenes/resonator.json similarity index 93% rename from src/webpages/cn/gallery/resonator.json rename to data/galleryScenes/resonator.json index b11d28d4..27bebcbb 100644 --- a/src/webpages/cn/gallery/resonator.json +++ b/data/galleryScenes/resonator.json @@ -111,26 +111,26 @@ "type": "TextLabel", "x": 766.4047619047619, "y": 431.2095238095238, - "text": "平面镜" + "text": "{{flatmirror}}" }, { "type": "TextLabel", "x": 591.0547619047619, "y": 427.0011904761904, - "text": "球形凹面镜", + "text": "{{sphericalconcavemirr}}", "alignment": "right" }, { "type": "TextLabel", "x": 1210.205952380952, "y": 484.77023809523774, - "text": "不稳定的共振腔" + "text": "{{unstableresonator}}" }, { "type": "TextLabel", "x": 520.9845238095238, "y": 493.66071428571416, - "text": "稳定的共振腔", + "text": "{{stableresonator}}", "alignment": "right" }, { @@ -164,6 +164,5 @@ "x": 344.6986542443067, "y": 208.88426501035215 }, - "scale": 1, - "name": "平凹共振腔" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/tw/gallery/retroreflectors.json b/data/galleryScenes/retroreflectors.json similarity index 96% rename from src/webpages/tw/gallery/retroreflectors.json rename to data/galleryScenes/retroreflectors.json index ff980078..5b4f4a0f 100644 --- a/src/webpages/tw/gallery/retroreflectors.json +++ b/data/galleryScenes/retroreflectors.json @@ -226,7 +226,7 @@ "type": "TextLabel", "x": 1529.732420828533, "y": 718.1146426079544, - "text": "拖曳此處\n可旋轉光束", + "text": "{{dragtorotatethebeam}}", "fontSize": 18, "alignment": "right" }, @@ -234,14 +234,14 @@ "type": "TextLabel", "x": 984.2775143314573, "y": 273.79378187562054, - "text": "貓眼回覆反射器", + "text": "{{catseyeretroreflecto}}", "alignment": "center" }, { "type": "TextLabel", "x": 976.2775143314573, "y": 827.7937818756205, - "text": "角隅反射器", + "text": "{{cornerretroreflector}}", "alignment": "center" }, { @@ -274,6 +274,5 @@ "x": -145.87623241020697, "y": 170.59028886173468 }, - "scale": 1, - "name": "回復反射器" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/tw/gallery/rochester-cloak.json b/data/galleryScenes/rochester-cloak.json similarity index 93% rename from src/webpages/tw/gallery/rochester-cloak.json rename to data/galleryScenes/rochester-cloak.json index c1cd283a..a9bebbee 100644 --- a/src/webpages/tw/gallery/rochester-cloak.json +++ b/data/galleryScenes/rochester-cloak.json @@ -1,6 +1,5 @@ { "version": 5, - "name": "羅徹斯特斗篷", "objs": [ { "type": "PointSource", @@ -157,34 +156,34 @@ "type": "TextLabel", "x": 1304.41728, "y": 677.86802, - "text": "觀察者(看不到部分隱形區域中的物體,\n但是可以看到可視區域中的物體)" + "text": "{{observerdoesntseethe}}" }, { "type": "TextLabel", "x": 731.627983238983, "y": 791.2114110116363, - "text": "部分隱形區域", + "text": "{{partialinvisibilitya}}", "alignment": "center" }, { "type": "TextLabel", "x": 523.7611963945017, "y": 689.1647798121937, - "text": "物體", + "text": "{{object}}", "alignment": "center" }, { "type": "TextLabel", "x": 744.0550188738907, "y": 640, - "text": "8個物體", + "text": "{{t8objects}}", "alignment": "center" }, { "type": "TextLabel", "x": 458.08969363158343, "y": 719.2695194863097, - "text": "可視區域", + "text": "{{visibilityarea}}", "alignment": "right" }, { diff --git a/src/webpages/tw/gallery/sea-mirage.json b/data/galleryScenes/sea-mirage.json similarity index 97% rename from src/webpages/tw/gallery/sea-mirage.json rename to data/galleryScenes/sea-mirage.json index 29efa0b8..8754bcbb 100644 --- a/src/webpages/tw/gallery/sea-mirage.json +++ b/data/galleryScenes/sea-mirage.json @@ -1,6 +1,5 @@ { "version": 5, - "name": "海市蜃樓", "objs": [ { "type": "CircleGrinGlass", @@ -301,7 +300,7 @@ "type": "TextLabel", "x": 719.1758859926426, "y": 886.4005602240895, - "text": "地球表面", + "text": "{{earthssurface}}", "fontSize": 45, "alignment": "center" }, @@ -309,28 +308,28 @@ "type": "TextLabel", "x": 106.57885182948164, "y": 926.4005602240891, - "text": "大氣層", + "text": "{{atmosphere}}", "fontSize": 45 }, { "type": "TextLabel", "x": 1323.9672553063717, "y": 1041.4005602240893, - "text": "建築/高山", + "text": "{{architecturealpine}}", "fontSize": 45 }, { "type": "TextLabel", "x": 498.444692613495, "y": 433.0375236878842, - "text": "觀察者", + "text": "{{observer1}}", "fontSize": 45 }, { "type": "TextLabel", "x": 421.49756943801776, "y": 187.11484593837534, - "text": "真空", + "text": "{{vacuum}}", "fontSize": 45, "alignment": "right" }, @@ -338,14 +337,14 @@ "type": "TextLabel", "x": 1225.8608405672267, "y": 423.8001403448874, - "text": "虚像", + "text": "{{virtualimage1}}", "fontSize": 45 }, { "type": "TextLabel", "x": 361.3932540948824, "y": 1421.4005602240893, - "text": "真空", + "text": "{{vacuum}}", "fontSize": 45, "alignment": "right" }, @@ -353,7 +352,7 @@ "type": "TextLabel", "x": 1150.2728836519623, "y": 1404.2577030812322, - "text": "真空", + "text": "{{vacuum}}", "fontSize": 45 }, { diff --git a/src/webpages/tw/gallery/simple-double-gauss-lens.json b/data/galleryScenes/simple-double-gauss-lens.json similarity index 99% rename from src/webpages/tw/gallery/simple-double-gauss-lens.json rename to data/galleryScenes/simple-double-gauss-lens.json index 7ee76a3b..714ac8c1 100644 --- a/src/webpages/tw/gallery/simple-double-gauss-lens.json +++ b/data/galleryScenes/simple-double-gauss-lens.json @@ -1,6 +1,5 @@ { "version": 5, - "name": "簡易雙高斯透鏡", "objs": [ { "type": "SphericalLens", diff --git a/src/webpages/gallery/single-ray-demo.json b/data/galleryScenes/single-ray-demo.json similarity index 99% rename from src/webpages/gallery/single-ray-demo.json rename to data/galleryScenes/single-ray-demo.json index 491f2762..23959aa4 100644 --- a/src/webpages/gallery/single-ray-demo.json +++ b/data/galleryScenes/single-ray-demo.json @@ -267,6 +267,5 @@ "x": 373.62551319648054, "y": 269.041055718475 }, - "scale": 1, - "name": "Single Ray demo" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/gallery/solar-eclipses.json b/data/galleryScenes/solar-eclipses.json similarity index 93% rename from src/webpages/gallery/solar-eclipses.json rename to data/galleryScenes/solar-eclipses.json index 7d58346c..4d476510 100644 --- a/src/webpages/gallery/solar-eclipses.json +++ b/data/galleryScenes/solar-eclipses.json @@ -1,6 +1,5 @@ { "version": 5, - "name": "Solar Eclipses", "modules": { "CircleSource": { "numPoints": 1, @@ -164,70 +163,70 @@ "type": "TextLabel", "x": 1376.6666666666667, "y": 415.6666666666667, - "text": "(Not to scale)", + "text": "{{nottoscale}}", "alignment": "right" }, { "type": "TextLabel", "x": 385, "y": 439, - "text": "Sun", + "text": "{{sun}}", "alignment": "center" }, { "type": "TextLabel", "x": 1043, "y": 631, - "text": "Moon", + "text": "{{moon}}", "alignment": "center" }, { "type": "TextLabel", "x": 1226, "y": 591, - "text": "Partial eclipse", + "text": "{{partialeclipse}}", "fontSize": 16 }, { "type": "TextLabel", "x": 1196, "y": 704, - "text": "Annular eclipse", + "text": "{{annulareclipse}}", "fontSize": 16 }, { "type": "TextLabel", "x": 1283, "y": 666, - "text": "Earth", + "text": "{{earth}}", "alignment": "center" }, { "type": "TextLabel", "x": 1294, "y": 215, - "text": "Earth", + "text": "{{earth}}", "alignment": "center" }, { "type": "TextLabel", "x": 1092, "y": 280, - "text": "Moon", + "text": "{{moon}}", "alignment": "center" }, { "type": "TextLabel", "x": 1221, "y": 154, - "text": "Partial eclipse", + "text": "{{partialeclipse}}", "fontSize": 16 }, { "type": "TextLabel", "x": 1226, "y": 253, - "text": "Total eclipse", + "text": "{{totaleclipse}}", "fontSize": 16 }, { diff --git a/src/webpages/cn/gallery/specular-and-diffuse-reflection.json b/data/galleryScenes/specular-and-diffuse-reflection.json similarity index 94% rename from src/webpages/cn/gallery/specular-and-diffuse-reflection.json rename to data/galleryScenes/specular-and-diffuse-reflection.json index f1c1561c..7082c3dc 100644 --- a/src/webpages/cn/gallery/specular-and-diffuse-reflection.json +++ b/data/galleryScenes/specular-and-diffuse-reflection.json @@ -50,14 +50,14 @@ "type": "TextLabel", "x": 412.6823529411765, "y": 574.3411764705883, - "text": "镜面反射", + "text": "{{specular}}", "alignment": "center" }, { "type": "TextLabel", "x": 732.8823529411766, "y": 576.3411764705883, - "text": "漫反射", + "text": "{{diffuse}}", "alignment": "center" }, { @@ -98,6 +98,5 @@ "x": 125.04519807923168, "y": -71.7442376950782 }, - "scale": 1, - "name": "镜面反射与漫反射" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/cn/gallery/spherical-lens-and-mirror.json b/data/galleryScenes/spherical-lens-and-mirror.json similarity index 97% rename from src/webpages/cn/gallery/spherical-lens-and-mirror.json rename to data/galleryScenes/spherical-lens-and-mirror.json index 247cbf0d..2cb48424 100644 --- a/src/webpages/cn/gallery/spherical-lens-and-mirror.json +++ b/data/galleryScenes/spherical-lens-and-mirror.json @@ -93,6 +93,5 @@ "x": 168.04838709677418, "y": 159.66129032258058 }, - "scale": 1, - "name": "球面透镜与面镜" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/cn/gallery/telescope.json b/data/galleryScenes/telescope.json similarity index 94% rename from src/webpages/cn/gallery/telescope.json rename to data/galleryScenes/telescope.json index c3bb115c..974b45b9 100644 --- a/src/webpages/cn/gallery/telescope.json +++ b/data/galleryScenes/telescope.json @@ -238,41 +238,41 @@ "type": "TextLabel", "x": -1448.6666666666663, "y": 113.99999999999999, - "text": "来自星体2的光", + "text": "{{lightfromstar2}}", "alignment": "center" }, { "type": "TextLabel", "x": -760.6666666666669, "y": -146, - "text": "来自星体1的光", + "text": "{{lightfromstar1}}", "alignment": "center" }, { "type": "TextLabel", "x": 1516, "y": 392, - "text": "使用伽利略扩束镜(更好地分离两颗星体的角度)" + "text": "{{withagallileanbeamex}}" }, { "type": "TextLabel", "x": 1257.3333333333333, "y": 1691.3333333333333, - "text": "屏幕", + "text": "{{screen1}}", "alignment": "center" }, { "type": "TextLabel", "x": 1257.3333333333337, "y": 871.3333333333334, - "text": "屏幕", + "text": "{{screen1}}", "alignment": "center" }, { "type": "TextLabel", "x": 1516, "y": 1212, - "text": "没有扩束镜" + "text": "{{withoutabeamexpander}}" }, { "type": "CropBox", @@ -304,6 +304,5 @@ "x": 2605.0526315789475, "y": 1214.3358395989976 }, - "scale": 1, - "name": "望远镜" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/tw/gallery/the-mirascope.json b/data/galleryScenes/the-mirascope.json similarity index 94% rename from src/webpages/tw/gallery/the-mirascope.json rename to data/galleryScenes/the-mirascope.json index fe371b37..1b0aaf01 100644 --- a/src/webpages/tw/gallery/the-mirascope.json +++ b/data/galleryScenes/the-mirascope.json @@ -1,18 +1,17 @@ { - "name": "幻象鏡", "version": 5, "objs": [ { "type": "TextLabel", "x": -520, "y": 700, - "text": "物體" + "text": "{{object1}}" }, { "type": "TextLabel", "x": -640.923076923077, "y": 360, - "text": "實像", + "text": "{{realimage1}}", "alignment": "right" }, { @@ -187,8 +186,8 @@ } } ], - "width": 1643.39076923077, - "height": 1100.3913846153848, + "width": 900, + "height": 1200, "rayModeDensity": 0.19602756340925195, "imageModeDensity": 0.11889672735647365, "observer": { @@ -199,9 +198,9 @@ "r": 20 }, "origin": { - "x": 1404.528631189924, - "y": 44.490369075714625 + "x": 962.809651417896, + "y": 170.0378135981059 }, - "scale": 1, + "scale": 0.5, "simulateColors": true } \ No newline at end of file diff --git a/src/webpages/cn/gallery/the-principle-of-camera-imaging.json b/data/galleryScenes/the-principle-of-camera-imaging.json similarity index 96% rename from src/webpages/cn/gallery/the-principle-of-camera-imaging.json rename to data/galleryScenes/the-principle-of-camera-imaging.json index 9a94c177..94995114 100644 --- a/src/webpages/cn/gallery/the-principle-of-camera-imaging.json +++ b/data/galleryScenes/the-principle-of-camera-imaging.json @@ -1,5 +1,4 @@ { - "name": "相机成像原理", "version": 5, "objs": [ { @@ -58,14 +57,14 @@ "type": "TextLabel", "x": 199.55899596667035, "y": 367.9691032858637, - "text": "外面的物体", + "text": "{{objectsoutside}}", "alignment": "right" }, { "type": "TextLabel", "x": 913.5043956043952, "y": 392.9062845651083, - "text": "相机", + "text": "{{camera}}", "alignment": "center" }, { @@ -133,7 +132,7 @@ "type": "TextLabel", "x": 1066.2885915124061, "y": 423.45358025984, - "text": "CMOS" + "text": "{{cmos}}" } ], "width": 2278.1297368421056, diff --git a/src/webpages/tw/gallery/transverse-and-longitudinal-magnification.json b/data/galleryScenes/transverse-and-longitudinal-magnification.json similarity index 87% rename from src/webpages/tw/gallery/transverse-and-longitudinal-magnification.json rename to data/galleryScenes/transverse-and-longitudinal-magnification.json index 7e771654..ffc819fb 100644 --- a/src/webpages/tw/gallery/transverse-and-longitudinal-magnification.json +++ b/data/galleryScenes/transverse-and-longitudinal-magnification.json @@ -72,7 +72,7 @@ "type": "TextLabel", "x": -646.6666666666667, "y": 470, - "text": "在這個例子中,我們有 y'_j - y'_k = M_T * (y_j - y_k),其中 j,k∈{0,1,2,3,4,5}。\n因此,例如點物體(x_0,y_0)的橫向放大率是 M_T = -3,我們可以計算 -\n(x'_0 - x'_1)/(x_1 - x_0) ≈ -0.3699\n(x'_0 - x'_2)/(x_2 - x_0) ≈ -0.7297\n(x'_0 - x'_3)/(x_3 - x_0) ≈ -1.4211\n(x'_0 - x'_4)/(x_4 - x_0) ≈ -2.4545\n(x'_0 - x'_5)/(x_5 - x_0) = -5.4\n.\n.\n.\n(這個比值將趨近於縱向放大率:M_L = - (M_T)^2 = -9)" + "text": "{{inthisexamplewehavey}}" }, { "type": "TextLabel", @@ -90,7 +90,7 @@ "type": "TextLabel", "x": 1420, "y": 380, - "text": "在(實)物上點擊右鍵以查看其座標。\n綠色的方塊是實際的點光源,黃色的方塊是像。" + "text": "{{rightclickonarealobj}}" }, { "type": "TextLabel", @@ -257,6 +257,5 @@ "x": 1536.0452488687788, "y": 579.2036199095023 }, - "scale": 1, - "name": "橫向和縱向放大率" + "scale": 1 } \ No newline at end of file diff --git a/src/webpages/gallery/vanishing-point-background.png b/data/galleryScenes/vanishing-point-background.png similarity index 100% rename from src/webpages/gallery/vanishing-point-background.png rename to data/galleryScenes/vanishing-point-background.png diff --git a/src/webpages/cn/gallery/vanishing-point.json b/data/galleryScenes/vanishing-point.json similarity index 91% rename from src/webpages/cn/gallery/vanishing-point.json rename to data/galleryScenes/vanishing-point.json index 5c15570e..03819521 100644 --- a/src/webpages/cn/gallery/vanishing-point.json +++ b/data/galleryScenes/vanishing-point.json @@ -244,20 +244,20 @@ "type": "TextLabel", "x": 1560, "y": 580, - "text": "你可以验证一对斜率为 m 的平行线,经过理想透镜收敛到座标 (f,m∙f),\n通过点击“网格”按钮,并注意到每个网格单元的尺寸为20乘以20。\n你也可以验证改变理想透镜的焦距 f 时,收敛点(消失点)会如何受到影响。" + "text": "{{youcanverifythatapai}}" }, { "type": "TextLabel", "x": 570.5714285714287, "y": 1024, - "text": "这对平行线聚集到点B", + "text": "{{thesepairofparallell}}", "alignment": "center" }, { "type": "TextLabel", "x": 871.7142857142858, "y": 588, - "text": "这对平行线聚集到点A", + "text": "{{thesepairofparallell1}}", "alignment": "right" }, { @@ -276,7 +276,7 @@ "type": "TextLabel", "x": -860, "y": 1100, - "text": "注意这些平行线实际上并不是无穷大。" + "text": "{{notethatthesepairsof}}" }, { "type": "CropBox", @@ -318,6 +318,5 @@ }, "scale": 1, "simulateColors": true, - "name": "消失点", "backgroundImage": "vanishing-point-background.png" } \ No newline at end of file diff --git a/src/webpages/gallery/zoom-lens.json b/data/galleryScenes/zoom-lens.json similarity index 97% rename from src/webpages/gallery/zoom-lens.json rename to data/galleryScenes/zoom-lens.json index 15b50204..bac5108c 100644 --- a/src/webpages/gallery/zoom-lens.json +++ b/data/galleryScenes/zoom-lens.json @@ -210,7 +210,7 @@ "type": "TextLabel", "x": 617.9729729729733, "y": 639.2972972972968, - "text": "Drag to move the lens", + "text": "{{dragtomovethelens}}", "fontSize": 16, "alignment": "center" }, @@ -218,7 +218,7 @@ "type": "TextLabel", "x": 622.4594594594595, "y": 326, - "text": "← zoom →", + "text": "{{zoom}}", "alignment": "center" }, { @@ -250,6 +250,5 @@ "x": 142.4884169884171, "y": -43.071428571428555 }, - "scale": 1, - "name": "Zoom Lens" + "scale": 1 } \ No newline at end of file diff --git a/data/localeRoutes.json b/data/localeRoutes.json new file mode 100644 index 00000000..b8d65e9c --- /dev/null +++ b/data/localeRoutes.json @@ -0,0 +1,6 @@ +{ + "en": "", + "ja": "/jp", + "zh-CN": "/cn", + "zh-TW": "/tw" +} \ No newline at end of file diff --git a/data/moduleList.json b/data/moduleList.json new file mode 100644 index 00000000..5a822aff --- /dev/null +++ b/data/moduleList.json @@ -0,0 +1,52 @@ +[ + { + "id": "defaultCategory", + "content": [ + { + "id": "FresnelLens", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "ContSpectrum", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "CircleSource", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "Chaff", + "contributors": [ + "Stas Fainer", + "Yi-Ting Tu" + ] + }, + { + "id": "BeamExpander", + "contributors": [ + "Yi-Ting Tu" + ] + }, + { + "id": "RayRelay", + "contributors": [ + "Stas Fainer", + "Yi-Ting Tu" + ] + }, + { + "id": "OpticalFiber", + "contributors": [ + "josephernest", + "Yi-Ting Tu" + ] + } + ] + } +] \ No newline at end of file diff --git a/src/webpages/modules/BeamExpander.json b/data/moduleScenes/BeamExpander.json similarity index 100% rename from src/webpages/modules/BeamExpander.json rename to data/moduleScenes/BeamExpander.json diff --git a/src/webpages/modules/Chaff.json b/data/moduleScenes/Chaff.json similarity index 100% rename from src/webpages/modules/Chaff.json rename to data/moduleScenes/Chaff.json diff --git a/src/webpages/modules/CircleSource.json b/data/moduleScenes/CircleSource.json similarity index 100% rename from src/webpages/modules/CircleSource.json rename to data/moduleScenes/CircleSource.json diff --git a/src/webpages/modules/ContSpectrum.json b/data/moduleScenes/ContSpectrum.json similarity index 100% rename from src/webpages/modules/ContSpectrum.json rename to data/moduleScenes/ContSpectrum.json diff --git a/src/webpages/modules/FresnelLens.json b/data/moduleScenes/FresnelLens.json similarity index 100% rename from src/webpages/modules/FresnelLens.json rename to data/moduleScenes/FresnelLens.json diff --git a/src/webpages/modules/OpticalFiber.json b/data/moduleScenes/OpticalFiber.json similarity index 100% rename from src/webpages/modules/OpticalFiber.json rename to data/moduleScenes/OpticalFiber.json diff --git a/src/webpages/modules/RayRelay.json b/data/moduleScenes/RayRelay.json similarity index 100% rename from src/webpages/modules/RayRelay.json rename to data/moduleScenes/RayRelay.json diff --git a/locales/de.json b/locales/de.json deleted file mode 100644 index 22294bdb..00000000 --- a/locales/de.json +++ /dev/null @@ -1,995 +0,0 @@ -{ - "appName": { - "message": "Simulator - Strahlenoptik-Simulation" - }, - "appShortName": { - "message": "Strahlenoptik" - }, - "appDesc": { - "message": "Eine freie, open-source Web-Applikation zum Erzeugen und Simulieren von optischen 2D-Szenen." - }, - "homepage_desc": { - "message": "Erstellen und simulieren Sie 2D geometrische optische Szenen interaktiv.
Völlig kostenlos und webbasiert. Der Quellcode ist auf GitHub verfügbar." - }, - "launch_simulator": { - "message": "Simulator starten" - }, - "home": { - "message": "Home" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/de/" - }, - "gallery": { - "message": "Galerie" - }, - "gallery_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "message": "Willkommen bei der Strahlenoptik-Simulation
Um eine optische Komponente hinzuzufügen, wählen Sie ein Werkzeug aus und klicken Sie auf das leere Feld.
Um ein Beispiel zu laden, wechseln Sie bitte zur Galerie." - }, - "loading_msg": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
Loading scene from URL... Please wait." - }, - "toolbar_title": { - "message": "Werkzeug: " - }, - "toolname_SingleRay": { - "message": "Einzelstrahl" - }, - "toolname_AngleSource": { - "message": "Punktquelle" - }, - "toolname_PointSource": { - "message": "Punktquelle" - }, - "toolname_Beam": { - "message": "Paralleles Bündel" - }, - "toolname_mirror_": { - "message": "Spiegel" - }, - "toolname_Mirror": { - "message": "Spiegel" - }, - "toolname_ArcMirror": { - "message": "Gebogener Spiegel" - }, - "toolname_ParabolicMirror": { - "message": "Parabolspiegel" - }, - "toolname_CustomMirror": { - "message": "Spiegel" - }, - "toolname_IdealMirror": { - "message": "Ideal gebogener Spiegel" - }, - "toolname_glass_": { - "message": "Glas" - }, - "toolname_blocker_": { - "message": "Absorber" - }, - "toolname_BeamSplitter": { - "message": "Strahlteiler" - }, - "toolname_PlaneGlass": { - "message": "Glas" - }, - "toolname_CircleGlass": { - "message": "Kreisförmiger Glaskörper" - }, - "toolname_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_Glass": { - "message": "Glas" - }, - "toolname_GrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_IdealLens": { - "message": "Ideale Linse" - }, - "toolname_SphericalLens": { - "message": "Sphärische Linse" - }, - "toolname_CustomGlass": { - "message": "Glas" - }, - "toolname_Blocker": { - "message": "Linienförmiger Absorber" - }, - "toolname_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "toolname_CircleBlocker": { - "message": "Kreisförmiger Absorber" - }, - "toolname_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "toolname_Ruler": { - "message": "Lineal" - }, - "toolname_Protractor": { - "message": "Winkelmesser" - }, - "tool_Detector": { - "message": "Detektor" - }, - "toolname_Detector": { - "message": "Detektor" - }, - "toolname_TextLabel": { - "message": "Text" - }, - "toolname_LineArrow": { - "incomplete": true, - "message": "Line" - }, - "toolname_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "toolname_Handle": { - "incomplete": true, - "message": "Handle" - }, - "toolname_CropBox": { - "incomplete": true, - "message": "Export" - }, - "toolname_ModuleObj": { - "incomplete": true, - "message": "ModuleBeta" - }, - "tool_more_": { - "message": "Andere" - }, - "toolname_": { - "message": "Ansicht bewegen" - }, - "modebar_title": { - "message": "Ansicht:" - }, - "modename_light": { - "message": "Strahlen" - }, - "modename_extended_light": { - "message": "Virtuelle Strahlen" - }, - "modename_images": { - "message": "Alle Abbildungen" - }, - "modename_observer": { - "message": "Beobachterperspektive" - }, - "simulateColors": { - "message": "Farben simulieren" - }, - "File: ": { - "message": "Datei" - }, - "Tools: ": { - "message": "Werkzeuge" - }, - "tool_SingleRay": { - "message": "Strahl" - }, - "tool_Beam": { - "message": "Bündel" - }, - "tool_PointSource": { - "message": "Punktquelle (360°)" - }, - "tool_AngleSource": { - "message": "Punktquelle (<360°)" - }, - "tool_PointSource_": { - "message": "Punktquelle" - }, - "tool_lightSource_": { - "message": "Lichtquelle" - }, - "tool_mirror_": { - "message": "Spiegel" - }, - "tool_Mirror": { - "message": "Segment" - }, - "tool_ArcMirror": { - "message": "Kreisbogen" - }, - "tool_ParabolicMirror": { - "message": "Parabolspiegel" - }, - "tool_CustomMirror": { - "message": "Benutzerdefinierte Gleichung" - }, - "tool_BeamSplitter": { - "message": "Strahlteiler" - }, - "tool_IdealMirror": { - "message": "Ideal gebogen" - }, - "tool_glass_": { - "message": "Gläser" - }, - "tool_blocker_": { - "message": "Absorber" - }, - "tool_PlaneGlass": { - "message": "Halbraum" - }, - "tool_CircleGlass": { - "message": "Kugellinse" - }, - "tool_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index circle" - }, - "tool_Glass": { - "incomplete": true, - "message": "Polygon / Circular Arcs" - }, - "tool_GrinGlass": { - "incomplete": true, - "message": "Gradient-index polygon" - }, - "tool_IdealLens": { - "message": "Ideale Linse" - }, - "tool_SphericalLens": { - "message": "Sphärische Linse" - }, - "tool_CustomGlass": { - "message": "Benutzerdefinierte Gleichung" - }, - "tool_Blocker": { - "message": "Linienförmiger Absorber" - }, - "tool_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "tool_CircleBlocker": { - "message": "Kreisförmiger Absorber" - }, - "tool_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "tool_Ruler": { - "message": "Lineal" - }, - "tool_Protractor": { - "message": "Winkelmesser" - }, - "tool_TextLabel": { - "message": "Text" - }, - "tool_LineArrow": { - "incomplete": true, - "message": "Line / Arrow" - }, - "tool_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "tool_": { - "message": "Ansicht bewegen" - }, - "View: ": { - "message": "Ansicht" - }, - "Settings: ": { - "message": "Einstellungen" - }, - "moresettings": { - "incomplete": true, - "message": "More" - }, - "mode_rays": { - "message": "Strahlen" - }, - "mode_extended": { - "message": "Virtuelle Strahlen" - }, - "mode_images": { - "message": "Alle Abbildungen" - }, - "mode_observer": { - "message": "Beobachterperspektive" - }, - "zoom": { - "message": "Zoom" - }, - "help": { - "message": "Hilfe" - }, - "rayDensity": { - "message": "Strahl-Anzahldichte" - }, - "raydensity": { - "message": "Strahl-Anzahldichte:" - }, - "undo": { - "message": "Rückgängig" - }, - "redo": { - "message": "Wiederherstellen" - }, - "reset": { - "message": "Zurücksetzen" - }, - "save": { - "message": "Speichern" - }, - "rename": { - "incomplete": true, - "message": "Rename" - }, - "get_link": { - "incomplete": true, - "message": "Copy Shareable Link" - }, - "export_svg": { - "incomplete": true, - "message": "Export as PNG/SVG" - }, - "view_gallery": { - "message": "Galerie ansehen" - }, - "save_name": { - "message": "Name" - }, - "save_cancel": { - "message": "Abbrechen" - }, - "save_description": { - "incomplete": true, - "message": "" - }, - "open": { - "message": "Öffnen" - }, - "layoutaids": { - "incomplete": true, - "message": "Layout Aids" - }, - "lockObjs": { - "message": "Objekte sperren" - }, - "showGrid": { - "message": "Raster" - }, - "snapToGrid": { - "message": "Anrasten" - }, - "snaptogrid": { - "message": "Anrasten" - }, - "length_unit_popover": { - "incomplete": true, - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "incomplete": true, - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "incomplete": true, - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "message": "Helligkeit" - }, - "wavelength": { - "message": "Wellenlänge (nm)" - }, - "dichroic": { - "message": "Dichroitische" - }, - "filter": { - "message": "Filter" - }, - "bandwidth": { - "message": "Bandbreite (nm)" - }, - "invert": { - "incomplete": true, - "message": "Invert" - }, - "emisAngle": { - "message": "Emissionswinkel (°)" - }, - "mirrored": { - "incomplete": true, - "message": "Mirrored" - }, - "lineDensity": { - "incomplete": true, - "message": "Lines/mm" - }, - "slitRatio": { - "incomplete": true, - "message": "Slit width / line spacing" - }, - "customBrightness": { - "incomplete": true, - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "incomplete": true, - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "message": "symmetrisch" - }, - "eqn_note": { - "incomplete": true, - "message": "" - }, - "symbolic_grin": { - "incomplete": true, - "message": "Symbolic body-merging" - }, - "grin_refractive_index": { - "incomplete": true, - "message": "" - }, - "symbolic_grin_note_popover": { - "incomplete": true, - "message": "

This toggle applies to all GRIN objects in the simulation.

This simulator has currently two implementations of light propagation between different mediums, for GRIN objects - numerical and symbolic (see 'multRefIndex' and 'devRefIndex' functions in 'CircleGrinGlass.js').

The numerical implementation is faster but doesn't always work properly (depending on the specific case) in scenarios when used with more than one GRIN object, such that at least one of them has a refractive index function which is not defined in the entire plane, while the symbolic implementation is slower but robust to such problems.

" - }, - "focalLength": { - "message": "Brennweite" - }, - "cartesianSign": { - "message": "Kartesische Zeichenkonvention" - }, - "refIndex": { - "message": "Brechungsindex*" - }, - "radii_of_curvature": { - "incomplete": true, - "message": "Radii of Curvature" - }, - "focal_distances": { - "incomplete": true, - "message": "Focal Distances" - }, - "refIndex_origin": { - "incomplete": true, - "message": "Origin of n(x,y)" - }, - "stepSize": { - "incomplete": true, - "message": "Numerical solver step size" - }, - "intersectTol": { - "incomplete": true, - "message": "Intersection tolerance" - }, - "random": { - "incomplete": true, - "message": "Random" - }, - "lambert": { - "incomplete": true, - "message": "Lambertian" - }, - "diameter": { - "incomplete": true, - "message": "Diameter" - }, - "irradMap": { - "incomplete": true, - "message": "Irradiance Map" - }, - "binSize": { - "incomplete": true, - "message": "Bin Size" - }, - "scaleInterval": { - "incomplete": true, - "message": "Scale interval" - }, - "exportData": { - "incomplete": true, - "message": "Export data" - }, - "demodulize": { - "incomplete": true, - "message": "Demodulize" - }, - "fontSize": { - "incomplete": true, - "message": "Font Size" - }, - "font": { - "incomplete": true, - "message": "Font" - }, - "fontStyle": { - "incomplete": true, - "message": "Style" - }, - "normal": { - "incomplete": true, - "message": "Normal" - }, - "bold": { - "incomplete": true, - "message": "Bold" - }, - "italic": { - "incomplete": true, - "message": "Italic" - }, - "bolditalic": { - "incomplete": true, - "message": "Bold Italic" - }, - "oblique": { - "incomplete": true, - "message": "Oblique" - }, - "boldoblique": { - "incomplete": true, - "message": "Bold Oblique" - }, - "alignment": { - "incomplete": true, - "message": "Alignment" - }, - "left": { - "incomplete": true, - "message": "Left" - }, - "center": { - "incomplete": true, - "message": "Centre" - }, - "right": { - "incomplete": true, - "message": "Right" - }, - "text_here": { - "incomplete": true, - "message": "Text Here" - }, - "smallCaps": { - "incomplete": true, - "message": "Small Caps" - }, - "angle": { - "incomplete": true, - "message": "Angle (°)" - }, - "arrow": { - "incomplete": true, - "message": "Forward arrow" - }, - "backArrow": { - "incomplete": true, - "message": "Backward arrow" - }, - "stop_drawing": { - "incomplete": true, - "message": "Finish Drawing" - }, - "cropBoxSize": { - "incomplete": true, - "message": "Crop Box Size" - }, - "format": { - "incomplete": true, - "message": "Format" - }, - "width": { - "incomplete": true, - "message": "Width" - }, - "rayCountLimit": { - "incomplete": true, - "message": "Ray count limit" - }, - "transformation": { - "incomplete": true, - "message": "TransformationBeta" - }, - "default": { - "incomplete": true, - "message": "Default" - }, - "translation": { - "incomplete": true, - "message": "Translation" - }, - "xTranslation": { - "incomplete": true, - "message": "X Translation" - }, - "yTranslation": { - "incomplete": true, - "message": "Y Translation" - }, - "rotation": { - "incomplete": true, - "message": "Rotation" - }, - "scaling": { - "incomplete": true, - "message": "Scaling" - }, - "beam_warning": { - "incomplete": true, - "message": "Image detection may not work with divergent/random beams." - }, - "image_detection_warning": { - "incomplete": true, - "message": "This tool does not support image detection." - }, - "non_simulateColors_warning": { - "incomplete": true, - "message": "This tool only works when \"Simulate Color\" is on." - }, - "brightness_note_popover": { - "incomplete": true, - "message": "

Only effective if 'Ray Density' is high enough.

To control the numbers of rays emitted, please adjust the global 'Ray Density' slider instead.

" - }, - "refIndex_note_popover": { - "message": "

*relativ, wenn Glaskörper überlappen

Wird dieses Objekt mit (absolutem) Brechungsindex n₁ simuliert, aber innerhalb eines anderen Glaskörpers mit Brechungsindex n₀ platziert, sollten Sie den Brechungsindex auf n₁/n₀ setzen. In komplizierten Fällen, bei denen mehrere Glaskörper überlappen, ergibt sich der effective Brechungsindex der überlappenden Region als Produkt der einzelnen Brechungsindizes.

" - }, - "stepSize_note_popover": { - "incomplete": true, - "message": "

Step size of Euler's method for solving the eikonal ray equation - see 'step' function and documentation inside the 'CircleGrinGlass.js' file, for more information.

" - }, - "eps_CircleGrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length]^2.

This numerical tolerance is used in the functions 'isOutsideGlass', 'isInsideGlass' and 'isOnBoundary', inside the 'CircleGrinGlass.js' file.

" - }, - "eps_GrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length].

This numerical tolerance is used in the functions 'isOnBoundary' and 'countIntersections', inside the 'GrinGlass.js' file.

" - }, - "cauchyCoeff": { - "message": "Cauchy Koeffizient" - }, - "transRatio": { - "message": "Transmissionsgrad" - }, - "applytoall": { - "message": "Alle anwenden" - }, - "duplicate": { - "message": "Duplizieren" - }, - "delete": { - "message": "Löschen" - }, - "unselect": { - "incomplete": true, - "message": "Unselect" - }, - "unselect_popover": { - "incomplete": true, - "message": "Unselect this object (Right-click on blank space has the same function.)" - }, - "showadvanced": { - "incomplete": true, - "message": "More options..." - }, - "processing": { - "message": "In Bearbeitung... hier klicken, um zu stoppen." - }, - "contribute": { - "message": "Mitmachen" - }, - "github": { - "message": "GitHub" - }, - "about": { - "message": "Über" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "message": "Helfen beim Übersetzen" - }, - "translated": { - "message": "übersetzt" - }, - "undo_popover": { - "message": "Letzte Aktion rückgängig machen. (Strg+Z)" - }, - "redo_popover": { - "message": "Letzte Aktion wieder herstellen. (Strg+Y)" - }, - "reset_popover": { - "message": "Alle Änderungen zurücksetzen." - }, - "save_popover": { - "message": "Die aktuelle Szene als Datei speichern." - }, - "open_popover": { - "message": "Öffnet eine existierende Datei oder ein Hintergrundbild. Das Hintergundbild wird relativ zum Koordinatenursprung angezeigt. (Oder Datei hierher ziehen.)" - }, - "get_link_popover": { - "incomplete": true, - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "message": "Die URL ist zu lang für einige Platformen. Es kann nötig sein die Datei zu \"Speichern\" und zu teilen." - }, - "export_svg_warning": { - "message": "Export als SVG-Datei. Farbmischungen und relative Brechungsindizes kleiner 1 sind nicht unterstützt." - }, - "export_ray_count_warning": { - "incomplete": true, - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "message": "Zur Galerie-Seite wechseln und ein Beispiel laden." - }, - "tool_SingleRay_popover": { - "message": "Ein einzelner Lichtstrahl, der durch zwei Punkte definiert ist. (Ziehen oder Klicken zum Erzeugen. Der erste Punkt ist die Quelle, die in Richtung des zweiten Punkts zielt.)" - }, - "tool_Beam_popover": { - "incomplete": true, - "message": "A parallel or divergent beam of rays emerges from a line segment, with density controlled by the 'Ray density' slider. (Drag or click to create.)" - }, - "tool_PointSource_popover": { - "message": "Strahlen entspringen aus einem einzigen Punkt, wobei die Zahl durch den Schieberegler \"Strahl-Anzahldichte\" eingestellt wird. (Klicken zum Erzeugen.)" - }, - "tool_AngleSource_popover": { - "message": "Punktquelle mit definiertem Emissions-Winkel." - }, - "tool_Mirror_popover": { - "message": "Simulieren Sie die Reflexion von Licht auf einem Spiegel. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_ArcMirror_popover": { - "message": "Ein Spiegel bestehend aus einem Kreisbogen, definiert durch drei Punkte. (Ziehen oder Klicken zum Erzeugen. Die ersten 2 Punkte definieren die Länge des Bogens, der letzte die Bogenkrümmung.)" - }, - "tool_ParabolicMirror_popover": { - "message": "Ein parabolischer Spiegel, definiert durch drei Punkte. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_CustomMirror_popover": { - "message": "Ein Spiegel dessen Form durch eine Gleichung y = f(x) bestimmt ist, wobei (x,y) transformierte Koordinaten sind mit den Randpunkten (-1,0) und (1,0). (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_BeamSplitter_popover": { - "message": "Ein Spiegel, der einen Teil der Lichtstrahlen durchlässt. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_IdealMirror_popover": { - "message": "Der idealisierte \"gekrümmte\" Spiegel, der die Spiegelgleichung (1/p + 1/q = 1/f) erfüllt. Die Brennweite kann direkt eingestellt werden. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_PlaneGlass_popover": { - "message": "Simulieren Sie die Brechung und Reflexion von Licht auf einer Oberfläche. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_CircleGlass_popover": { - "message": "Kreisförmiger Glaskörper, definiert durch Mittelpunkt und einen Punkt auf dem Umfang. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_CircleGrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a circular boundary. (Drag or click to create.)" - }, - "tool_Glass_popover": { - "message": "Beliebig gefortmer Glaskörper aus Liniensegmenten und Kreisbögen konstruiert. (Klicken, um ein Liniensegment zu erzeugen; Ziehen, um einen Kreisbogen zu erzeugen; auf den Startpunkt klicken, um die Form abzuschließen.)" - }, - "tool_GrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a polygonal boundary. WARNING: Only simple polygons are supported, otherwise the behavior is unpredictable. (Click to create a segment, click on the starting point when finish drawing.)" - }, - "tool_IdealLens_popover": { - "message": "Eine ideale Linse, die die Linsengleichung (1/p + 1/q = 1/f) erfüllt. Die Brennweite kann direkt eingestellt werden. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_SphericalLens_popover": { - "message": "Eine sphärische Linse. (Klicken zum Erzeugen.)" - }, - "tool_CustomGlass_popover": { - "message": "Glaskörper mit einer Form, welche durch eine benutzerspezifische Ungleichung f(x) < y < g(x) definiert ist, wobei (x,y) trransformierte Koordinaten sind mit den Randpunkten (-1,0) und (1,0). (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_Blocker_popover": { - "message": "Ein linienförmiger Absorber, der die einfallenden Strahlen absorbiert. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_Aperture_popover": { - "incomplete": true, - "message": "A pair of light blockers which absorbs the incident rays. The size of the hole can be adjusted symmetrically. (Drag or click the two endpoints to create.)" - }, - "tool_CircleBlocker_popover": { - "message": "Ein kreisförmiger Absorber. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_DiffractionGrating_popover": { - "incomplete": true, - "message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)" - }, - "tool_Ruler_popover": { - "message": "Ein Lineal von einem Nullpunkt bis zu einem anderen Punkt. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_Protractor_popover": { - "message": "Ein Winkelmesser, der vom Zentrum und einem anderen Punkt für die Nullrichtung definiert ist. Die Skala ist in Grad. (Ziehen oder Klicken zum Erzeugen.)" - }, - "tool_Detector_popover": { - "message": "Ein Messwerkzeug für Energieflussrate (P), der Rate des senkrechten Impulsflusses (F∩) und der Rate des parallelen Impulsflusses (F∥) durch ein Segment. (Ziehen oder Klicken zum Erzeugen.) Die Einheiten sind willkürlich." - }, - "tool_Detector_info_popover": { - "incomplete": true, - "message": "" - }, - "tool_TextLabel_popover": { - "message": "Ein Text-Label." - }, - "tool_LineArrow_popover": { - "incomplete": true, - "message": "A line segment or arrow. (Drag or click to create.)" - }, - "tool_Drawing_popover": { - "incomplete": true, - "message": "A freehand drawing tool. (Drag to draw.)" - }, - "tool__popover": { - "message": "Ziehen um die Ansicht zu Verschieben. (Rechte Maustaste hat die gleiche Funktion.)" - }, - "mode_rays_popover": { - "message": "In dieser Ansicht werden die Lichtstrahlen angezeigt. Wenn die \"Strahl-Anzahldichte\" hoch ist, scheinen sie kontinuierlich zu sein." - }, - "mode_extended_popover": { - "message": "In dieser Ansicht werden die Lichtstrahlen als auch ihre Verlängerungen angezeigt. Orange bezeichnet die Rückwärtsverlängerung, während Grau vorwärts deutet.
Wenn 'Farben simulieren' aktiv ist, werden die Quellfarben verwendet und stattdessen durch Strichelung unterschieden." - }, - "mode_images_popover": { - "message": "In dieser Ansicht wird die Position aller Bilder angezeigt. Gelb bedeutet echtes Bild, orange steht für virtuelle Bilder und grau (nicht in diesem Bild dargestellt) bedeutet virtuelles Objekt. Beachten Sie, dass einige Bilder nicht erkannt werden können, wenn die \"Strahl-Anzahldichte\" nicht hoch genug ist.
Wenn 'Farben simulieren' aktiv ist, werden Bilder in der Quellfarbe angezeigt, und stattdessen nach Punktgröße unterschieden." - }, - "mode_observer_popover": { - "message": "In dieser Ansicht werden die Strahlen und Bilder von der Beobachterperspektive angezeigt. Der blaue Punkt ist der Beobachter. Alle Strahlen, die ihn kreuzen, gelten als \"wird beobachtet\". Der Beobachter weiß nicht, wo die Strahlen tatsächlich beginnen, 'denkt' aber, dass sie an einem Punkt beginnen, an dem sie sich schneiden. Die Strahlen sind blau und die Punkte gelb (real) oder orange (virtuell) dargestellt. (Ziehen Sie den großen blauen Kreis um den Beobachter zu bewegen.)
Wenn 'Farben simulieren' aktiv ist, werden die Strahlen mit den Quellfarben dargestellt." - }, - "simulateColors_popover": { - "incomplete": true, - "message": "Simulate colors (wavelengths) of light sources, mixture of colors, color filtering of blockers and mirrors, and chromatic dispersion of glasses. You can set those parameters for those objects when selected. To simulate color spectra, overlap rays with different wavelengths. The colors shown on the screen are only rough approximations, and can be very inaccurate when 'Ray density' is too high or too low." - }, - "rayDensity_popover": { - "incomplete": true, - "message": "Determines the number of rays to be emitted by beams and point sources. This also affects the accuracy of image detection and color rendering." - }, - "showGrid_popover": { - "message": "Sichtbarkeit des Gitters." - }, - "grid_popover": { - "message": "Objekte auf dem Gitter einrasten." - }, - "lockObjs_popover": { - "message": "Verschieben von Objekten sperren." - }, - "zoom_popover": { - "message": "Ansicht zoomen. (in Prozent)" - }, - "help_popover": { - "incomplete": true, - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "incomplete": true, - "message": "Show help popups" - }, - "show_help_popups_popover": { - "incomplete": true, - "message": "Defines whether to show help popups when hovering over buttons. (Reload the page to take effect.)" - }, - "show_json_editor": { - "incomplete": true, - "message": "Show JSON editorBeta" - }, - "show_json_editor_popover": { - "incomplete": true, - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "incomplete": true, - "message": "Show status box" - }, - "show_status_popover": { - "incomplete": true, - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "incomplete": true, - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "incomplete": true, - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "incomplete": true, - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "incomplete": true, - "message": "Grid Size" - }, - "observer_size": { - "incomplete": true, - "message": "Observer Size" - }, - "language": { - "incomplete": true, - "message": "Language" - }, - "close": { - "incomplete": true, - "message": "Close" - }, - "advanced_help": { - "incomplete": true, - "message": "For advanced help, see the help icon in the lower-right corner." - }, - "ray_count": { - "incomplete": true, - "message": "Number of ray segments: " - }, - "total_truncation": { - "incomplete": true, - "message": "Truncated brightness: " - }, - "brightness_scale": { - "incomplete": true, - "message": "Brightness Scale: " - }, - "time_elapsed": { - "incomplete": true, - "message": "Time elapsed (ms): " - }, - "force_stopped": { - "incomplete": true, - "message": "Force stopped." - }, - "mouse_coordinates": { - "incomplete": true, - "message": "Mouse coordinates: " - }, - "modules_tutorial": { - "incomplete": true, - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "incomplete": true, - "message": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior." - }, - "import_modules": { - "incomplete": true, - "message": "Import Modules..." - }, - "import_modules_title": { - "incomplete": true, - "message": "Import Modules" - }, - "modules_url": { - "incomplete": true, - "message": "../modules/modules.html" - }, - "remove_module": { - "incomplete": true, - "message": "Remove module" - }, - "module_conflict": { - "incomplete": true, - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "incomplete": true, - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/de/main.json b/locales/de/main.json new file mode 100644 index 00000000..a74dee5e --- /dev/null +++ b/locales/de/main.json @@ -0,0 +1,171 @@ +{ + "meta": { + "languageName": "Deutsch", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "Strahlenoptik-Simulation", + "shortName": "Strahlenoptik", + "description": "Eine freie, open-source Web-Applikation zum Erzeugen und Simulieren von optischen 2D-Szenen." + }, + "pages": { + "simulator": "Simulator", + "home": "Home", + "gallery": "Galerie", + "about": "Über", + "github": "GitHub" + }, + "homePage": { + "description": "Erstellen und simulieren Sie 2D geometrische optische Szenen interaktiv.\nVöllig kostenlos und webbasiert. Der Quellcode ist [auf GitHub verfügbar](/github).", + "launchSimulator": "Simulator starten" + }, + "tools": { + "title": "Werkzeuge", + "categories": { + "lightSource": "Lichtquelle", + "mirror": "Spiegel", + "glass": "Gläser", + "blocker": "Absorber", + "other": "Andere" + }, + "common": { + "clickInstruction": "Klicken zum Erzeugen.", + "lineInstruction": "Ziehen oder Klicken zum Erzeugen.", + "circleInstruction": "Ziehen oder Klicken zum Erzeugen." + }, + "SingleRay": { + "title": "Strahl", + "description": "Ein einzelner Lichtstrahl, der durch zwei Punkte definiert ist.", + "instruction": "Ziehen oder Klicken zum Erzeugen. Der erste Punkt ist die Quelle, die in Richtung des zweiten Punkts zielt." + }, + "Beam": { + "title": "Bündel" + }, + "PointSource": { + "title": "Punktquelle", + "description": "Strahlen entspringen aus einem einzigen Punkt, wobei die Zahl durch den Schieberegler \"Strahl-Anzahldichte\" eingestellt wird." + }, + "AngleSource": { + "instruction": "Ziehen oder Klicken zum Erzeugen. Der erste Punkt ist die Quelle, die in Richtung des zweiten Punkts zielt.", + "description": "Punktquelle mit definiertem Emissions-Winkel." + }, + "Mirror": { + "title": "Segment", + "description": "Simulieren Sie die Reflexion von Licht auf einem Spiegel." + }, + "otherMirror": { + "title": "gebogen", + "description": "Ein Spiegel, dessen Form gebogen ist. Es kann kreisförmig, parabolisch oder durch eine benutzerdefinierte Gleichung y = f(x) definiert sein." + }, + "ArcMirror": { + "title": "Kreisbogen", + "description": "Ein Spiegel bestehend aus einem Kreisbogen, definiert durch drei Punkte.", + "instruction": "Ziehen oder Klicken zum Erzeugen. Die ersten 2 Punkte definieren die Länge des Bogens, der letzte die Bogenkrümmung." + }, + "ParabolicMirror": { + "title": "Parabolspiegel", + "description": "Ein parabolischer Spiegel, definiert durch drei Punkte.", + "instruction": "Ziehen oder Klicken zum Erzeugen." + }, + "CustomMirror": { + "title": "Benutzerdefinierte Gleichung", + "description": "Ein Spiegel dessen Form durch eine Gleichung y = f(x) bestimmt ist, wobei (x,y) transformierte Koordinaten sind mit den Randpunkten (-1,0) und (1,0)." + }, + "IdealMirror": { + "title": "Ideal gebogen", + "description": "Der idealisierte \"gekrümmte\" Spiegel, der die Spiegelgleichung (1/p + 1/q = 1/f) erfüllt. Die Brennweite kann direkt eingestellt werden." + }, + "BeamSplitter": { + "title": "Strahlteiler", + "description": "Ein Spiegel, der einen Teil der Lichtstrahlen durchlässt." + }, + "PlaneGlass": { + "title": "Halbraum", + "description": "Simulieren Sie die Brechung und Reflexion von Licht auf einer Oberfläche.", + "instruction": "Ziehen oder Klicken zum Erzeugen." + }, + "otherGlass": { + "title": "andere Formen", + "description": "Glas mit beliebigen Formen, die aus Segmenten und Kreisbögen bestehen, oder Formen, die durch eine benutzerdefinierte Ungleichung f(x) < y < g(x) definiert sind." + }, + "CircleGlass": { + "title": "Kugellinse", + "description": "Kreisförmiger Glaskörper, definiert durch Mittelpunkt und einen Punkt auf dem Umfang." + }, + "Glass": { + "description": "Beliebig gefortmer Glaskörper aus Liniensegmenten und Kreisbögen konstruiert.", + "instruction": "Klicken, um ein Liniensegment zu erzeugen; Ziehen, um einen Kreisbogen zu erzeugen; auf den Startpunkt klicken, um die Form abzuschließen." + }, + "CustomGlass": { + "title": "Benutzerdefinierte Gleichung", + "description": "Glaskörper mit einer Form, welche durch eine benutzerspezifische Ungleichung f(x) < y < g(x) definiert ist, wobei (x,y) trransformierte Koordinaten sind mit den Randpunkten (-1,0) und (1,0)." + }, + "IdealLens": { + "title": "Ideale Linse", + "description": "Eine ideale Linse, die die Linsengleichung (1/p + 1/q = 1/f) erfüllt. Die Brennweite kann direkt eingestellt werden." + }, + "SphericalLens": { + "title": "Sphärische Linse", + "description": "Eine sphärische Linse." + }, + "Blocker": { + "title": "Linienförmiger Absorber", + "description": "Ein linienförmiger Absorber, der die einfallenden Strahlen absorbiert." + }, + "CircleBlocker": { + "title": "Kreisförmiger Absorber", + "description": "Ein kreisförmiger Absorber." + }, + "Ruler": { + "title": "Lineal", + "description": "Ein Lineal von einem Nullpunkt bis zu einem anderen Punkt." + }, + "Protractor": { + "title": "Winkelmesser", + "description": "Ein Winkelmesser, der vom Zentrum und einem anderen Punkt für die Nullrichtung definiert ist. Die Skala ist in Grad." + }, + "Detector": { + "title": "Detektor", + "description": "Ein Messwerkzeug für Energieflussrate (P), der Rate des senkrechten Impulsflusses (F∩) und der Rate des parallelen Impulsflusses (F∥) durch ein Segment. Die Einheiten sind willkürlich." + }, + "TextLabel": { + "title": "Text", + "description": "Ein Text-Label." + }, + "moveView": { + "title": "Ansicht bewegen", + "description": "Ziehen um die Ansicht zu Verschieben. (Rechte Maustaste hat die gleiche Funktion.)" + } + }, + "view": { + "title": "Ansicht", + "rays": { + "title": "Strahlen", + "description": "In dieser Ansicht werden die Lichtstrahlen angezeigt. Wenn die \"Strahl-Anzahldichte\" hoch ist, scheinen sie kontinuierlich zu sein." + }, + "extended": { + "title": "Virtuelle Strahlen", + "description": "In dieser Ansicht werden die Lichtstrahlen als auch ihre Verlängerungen angezeigt. Orange bezeichnet die Rückwärtsverlängerung, während Grau vorwärts deutet.", + "simulateColorsNote": "Wenn 'Farben simulieren' aktiv ist, werden die Quellfarben verwendet und stattdessen durch Strichelung unterschieden." + }, + "images": { + "title": "Alle Abbildungen", + "description": "In dieser Ansicht wird die Position aller Bilder angezeigt. Gelb bedeutet echtes Bild, orange steht für virtuelle Bilder und grau (nicht in diesem Bild dargestellt) bedeutet virtuelles Objekt. Beachten Sie, dass einige Bilder nicht erkannt werden können, wenn die \"Strahl-Anzahldichte\" nicht hoch genug ist.", + "simulateColorsNote": "Wenn 'Farben simulieren' aktiv ist, werden Bilder in der Quellfarbe angezeigt, und stattdessen nach Punktgröße unterschieden." + }, + "observer": { + "title": "Beobachterperspektive", + "description": "In dieser Ansicht werden die Strahlen und Bilder von der Beobachterperspektive angezeigt. Der blaue Punkt ist der Beobachter. Alle Strahlen, die ihn kreuzen, gelten als \"wird beobachtet\". Der Beobachter weiß nicht, wo die Strahlen tatsächlich beginnen, 'denkt' aber, dass sie an einem Punkt beginnen, an dem sie sich schneiden. Die Strahlen sind blau und die Punkte gelb (real) oder orange (virtuell) dargestellt.", + "simulateColorsNote": "Wenn 'Farben simulieren' aktiv ist, werden die Strahlen mit den Quellfarben dargestellt.", + "instruction": "Ziehen Sie den großen blauen Kreis um den Beobachter zu bewegen." + } + }, + "simulateColors": { + "title": "Farben simulieren" + }, + "languageDropdown": { + "translatedFraction": "{{fraction}} übersetzt" + } +} \ No newline at end of file diff --git a/locales/de/simulator.json b/locales/de/simulator.json new file mode 100644 index 00000000..cb87765d --- /dev/null +++ b/locales/de/simulator.json @@ -0,0 +1,104 @@ +{ + "welcome": { + "title": "Willkommen bei der Strahlenoptik-Simulation", + "instruction": "Um eine optische Komponente hinzuzufügen, wählen Sie ein Werkzeug aus und klicken Sie auf das leere Feld.\nUm ein Beispiel zu laden, [wechseln Sie bitte zur Galerie](/gallery)." + }, + "common": { + "saveButton": "Speichern", + "cancelButton": "Abbrechen" + }, + "file": { + "title": "Datei", + "undo": { + "title": "Rückgängig" + }, + "redo": { + "title": "Wiederherstellen" + }, + "reset": { + "title": "Zurücksetzen" + }, + "save": { + "title": "Speichern" + }, + "open": { + "title": "Öffnen", + "description": "Öffnet eine existierende Datei oder ein Hintergrundbild. Das Hintergundbild wird relativ zum Koordinatenursprung angezeigt. (Oder Datei hierher ziehen.)" + }, + "viewGallery": { + "title": "Galerie ansehen", + "description": "Zur Galerie-Seite wechseln und ein Beispiel laden." + } + }, + "settings": { + "title": "Einstellungen", + "rayDensity": { + "title": "Strahl-Anzahldichte" + }, + "layoutAids": { + "showGrid": "Raster", + "snapToGrid": "Anrasten", + "lockObjs": "Objekte sperren" + }, + "zoom": { + "title": "Zoom" + } + }, + "objBar": { + "applyToAll": { + "title": "Alle anwenden" + }, + "duplicate": { + "title": "Duplizieren" + }, + "delete": { + "title": "Löschen" + } + }, + "sceneObjs": { + "common": { + "brightness": "Helligkeit", + "wavelength": "Wellenlänge", + "emisAngle": "Emissionswinkel", + "focalLength": "Brennweite" + }, + "AngleSource": { + "symmetric": "symmetrisch" + }, + "BaseFilter": { + "filter": "Filter", + "bandwidth": "Bandbreite" + }, + "IdealMirror": { + "cartesianSign": "Kartesische Zeichenkonvention" + }, + "BeamSplitter": { + "transRatio": "Transmissionsgrad" + }, + "BaseGlass": { + "refIndex": "Brechungsindex", + "refIndexInfo": { + "relative": "relativ, wenn Glaskörper überlappen", + "effective": "Wird dieses Objekt mit (absolutem) Brechungsindex n₁ simuliert, aber innerhalb eines anderen Glaskörpers mit Brechungsindex n₀ platziert, sollten Sie den Brechungsindex auf n₁/n₀ setzen. In komplizierten Fällen, bei denen mehrere Glaskörper überlappen, ergibt sich der effective Brechungsindex der überlappenden Region als Produkt der einzelnen Brechungsindizes." + }, + "cauchyCoeff": "Cauchy Koeffizient" + }, + "CropBox": { + "svgWarning": "Export als SVG-Datei. Farbmischungen und relative Brechungsindizes kleiner 1 sind nicht unterstützt." + } + }, + "saveModal": { + "title": "Speichern", + "fileName": "Name" + }, + "languageModal": { + "translatedFraction": "übersetzt", + "helpTranslate": "Helfen beim Übersetzen" + }, + "generalWarnings": { + "shareLinkTooLong": "Die URL ist zu lang für einige Platformen. Es kann nötig sein die Datei zu \"Speichern\" und zu teilen." + }, + "footer": { + "processing": "In Bearbeitung... hier klicken, um zu stoppen." + } +} \ No newline at end of file diff --git a/locales/en.json b/locales/en.json deleted file mode 100644 index 5eb67deb..00000000 --- a/locales/en.json +++ /dev/null @@ -1,863 +0,0 @@ -{ - "appName": { - "message": "Simulator - Ray Optics Simulation" - }, - "appShortName": { - "message": "Ray Optics" - }, - "appDesc": { - "message": "A free, open-source web app for creating and simulating 2D geometric optical scenes." - }, - "homepage_desc": { - "message": "Create & simulate 2D geometric optical scenes interactively.
Totally free and web-based. Source code is available on GitHub." - }, - "launch_simulator": { - "message": "Launch Simulator" - }, - "home": { - "message": "Home" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/" - }, - "gallery": { - "message": "Gallery" - }, - "gallery_url": { - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "message": "Welcome to Ray Optics Simulation
To add an optical component, select a tool and click the blank space.
To load an example, please go to the Gallery page." - }, - "loading_msg": { - "message": "Welcome to Ray Optics Simulation
Loading scene from URL... Please wait." - }, - "toolbar_title": { - "message": "Tool: " - }, - "toolname_SingleRay": { - "message": "Single ray" - }, - "toolname_AngleSource": { - "message": "Point source" - }, - "toolname_PointSource": { - "message": "Point source" - }, - "toolname_Beam": { - "message": "Beam" - }, - "toolname_mirror_": { - "message": "Mirror" - }, - "toolname_Mirror": { - "message": "Mirror" - }, - "toolname_ArcMirror": { - "message": "Mirror" - }, - "toolname_ParabolicMirror": { - "message": "Mirror" - }, - "toolname_CustomMirror": { - "message": "Mirror" - }, - "toolname_IdealMirror": { - "message": "Ideal curved mirror" - }, - "toolname_glass_": { - "message": "Glass" - }, - "toolname_blocker_": { - "message": "Blocker" - }, - "toolname_BeamSplitter": { - "message": "Beam Splitter" - }, - "toolname_PlaneGlass": { - "message": "Glass" - }, - "toolname_CircleGlass": { - "message": "Glass" - }, - "toolname_CircleGrinGlass": { - "message": "Gradient-index glass" - }, - "toolname_Glass": { - "message": "Glass" - }, - "toolname_GrinGlass": { - "message": "Gradient-index glass" - }, - "toolname_IdealLens": { - "message": "Ideal lens" - }, - "toolname_SphericalLens": { - "message": "Spherical lens" - }, - "toolname_CustomGlass": { - "message": "Glass" - }, - "toolname_Blocker": { - "message": "Line Blocker" - }, - "toolname_Aperture": { - "message": "Aperture" - }, - "toolname_CircleBlocker": { - "message": "Circle Blocker" - }, - "toolname_DiffractionGrating": { - "message": "Diffraction GratingBeta" - }, - "toolname_Ruler": { - "message": "Ruler" - }, - "toolname_Protractor": { - "message": "Protractor" - }, - "tool_Detector": { - "message": "Detector" - }, - "toolname_Detector": { - "message": "Detector" - }, - "toolname_TextLabel": { - "message": "Text" - }, - "toolname_LineArrow": { - "message": "Line" - }, - "toolname_Drawing": { - "message": "Drawing" - }, - "toolname_Handle": { - "message": "Handle" - }, - "toolname_CropBox": { - "message": "Export" - }, - "toolname_ModuleObj": { - "message": "ModuleBeta" - }, - "tool_more_": { - "message": "Other" - }, - "toolname_": { - "message": "Move view" - }, - "modebar_title": { - "message": "View:" - }, - "modename_light": { - "message": "Rays" - }, - "modename_extended_light": { - "message": "Extended rays" - }, - "modename_images": { - "message": "All Images" - }, - "modename_observer": { - "message": "Seen by observer" - }, - "simulateColors": { - "message": "Simulate Colors" - }, - "File: ": { - "message": "File" - }, - "Tools: ": { - "message": "Tools" - }, - "tool_SingleRay": { - "message": "Single ray" - }, - "tool_Beam": { - "message": "Beam" - }, - "tool_PointSource": { - "message": "Point source (360°)" - }, - "tool_AngleSource": { - "message": "Point source (<360°)" - }, - "tool_PointSource_": { - "message": "Point source" - }, - "tool_lightSource_": { - "message": "Light Source" - }, - "tool_mirror_": { - "message": "Mirror" - }, - "tool_Mirror": { - "message": "Segment" - }, - "tool_ArcMirror": { - "message": "Circular Arc" - }, - "tool_ParabolicMirror": { - "message": "Parabolic" - }, - "tool_CustomMirror": { - "message": "Custom Equation" - }, - "tool_BeamSplitter": { - "message": "Beam Splitter" - }, - "tool_IdealMirror": { - "message": "Ideal curved mirror" - }, - "tool_glass_": { - "message": "Glass" - }, - "tool_blocker_": { - "message": "Blocker" - }, - "tool_PlaneGlass": { - "message": "Half-plane" - }, - "tool_CircleGlass": { - "message": "Circle" - }, - "tool_CircleGrinGlass": { - "message": "Gradient-index circle" - }, - "tool_Glass": { - "message": "Polygon / Circular Arcs" - }, - "tool_GrinGlass": { - "message": "Gradient-index polygon" - }, - "tool_IdealLens": { - "message": "Ideal Lens" - }, - "tool_SphericalLens": { - "message": "Spherical Lens" - }, - "tool_CustomGlass": { - "message": "Custom Equation" - }, - "tool_Blocker": { - "message": "Line Blocker" - }, - "tool_Aperture": { - "message": "Aperture" - }, - "tool_CircleBlocker": { - "message": "Circle Blocker" - }, - "tool_DiffractionGrating": { - "message": "Diffraction GratingBeta" - }, - "tool_Ruler": { - "message": "Ruler" - }, - "tool_Protractor": { - "message": "Protractor" - }, - "tool_TextLabel": { - "message": "Text" - }, - "tool_LineArrow": { - "message": "Line / Arrow" - }, - "tool_Drawing": { - "message": "Drawing" - }, - "tool_": { - "message": "Move view" - }, - "View: ": { - "message": "View" - }, - "Settings: ": { - "message": "Settings" - }, - "moresettings": { - "message": "More" - }, - "mode_rays": { - "message": "Rays" - }, - "mode_extended": { - "message": "Extended rays" - }, - "mode_images": { - "message": "All Images" - }, - "mode_observer": { - "message": "Seen by Observer" - }, - "zoom": { - "message": "Zoom" - }, - "help": { - "message": "Help" - }, - "rayDensity": { - "message": "Ray Density" - }, - "raydensity": { - "message": "Ray Density:" - }, - "undo": { - "message": "Undo" - }, - "redo": { - "message": "Redo" - }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "rename": { - "message": "Rename" - }, - "get_link": { - "message": "Copy Shareable Link" - }, - "export_svg": { - "message": "Export as PNG/SVG" - }, - "view_gallery": { - "message": "View Gallery" - }, - "save_name": { - "message": "Name" - }, - "save_cancel": { - "message": "Cancel" - }, - "save_description": { - "message": "" - }, - "open": { - "message": "Open" - }, - "layoutaids": { - "message": "Layout Aids" - }, - "lockObjs": { - "message": "Lock Objects" - }, - "showGrid": { - "message": "Grid" - }, - "snapToGrid": { - "message": "Snap to Grid" - }, - "snaptogrid": { - "message": "Snap to Grid" - }, - "length_unit_popover": { - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "message": "Brightness" - }, - "wavelength": { - "message": "Wavelength (nm)" - }, - "dichroic": { - "message": "Dichroic" - }, - "filter": { - "message": "Filter" - }, - "bandwidth": { - "message": "Bandwidth (nm)" - }, - "invert": { - "message": "Invert" - }, - "emisAngle": { - "message": "Emission Angle (°)" - }, - "mirrored": { - "message": "Mirrored" - }, - "lineDensity": { - "message": "Lines/mm" - }, - "slitRatio": { - "message": "Slit width / line spacing" - }, - "customBrightness": { - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "message": "Symmetric" - }, - "eqn_note": { - "message": "" - }, - "symbolic_grin": { - "message": "Symbolic body-merging" - }, - "grin_refractive_index": { - "message": "" - }, - "symbolic_grin_note_popover": { - "message": "

This toggle applies to all GRIN objects in the simulation.

This simulator has currently two implementations of light propagation between different mediums, for GRIN objects - numerical and symbolic (see 'multRefIndex' and 'devRefIndex' functions in 'CircleGrinGlass.js').

The numerical implementation is faster but doesn't always work properly (depending on the specific case) in scenarios when used with more than one GRIN object, such that at least one of them has a refractive index function which is not defined in the entire plane, while the symbolic implementation is slower but robust to such problems.

" - }, - "focalLength": { - "message": "Focal length" - }, - "cartesianSign": { - "message": "Cartesian Sign Convention" - }, - "refIndex": { - "message": "Refractive index*" - }, - "radii_of_curvature": { - "message": "Radii of Curvature" - }, - "focal_distances": { - "message": "Focal Distances" - }, - "refIndex_origin": { - "message": "Origin of n(x,y)" - }, - "stepSize": { - "message": "Numerical solver step size" - }, - "intersectTol": { - "message": "Intersection tolerance" - }, - "random": { - "message": "Random" - }, - "lambert": { - "message": "Lambertian" - }, - "diameter": { - "message": "Diameter" - }, - "irradMap": { - "message": "Irradiance Map" - }, - "binSize": { - "message": "Bin Size" - }, - "scaleInterval": { - "message": "Scale interval" - }, - "exportData": { - "message": "Export data" - }, - "demodulize": { - "message": "Demodulize" - }, - "fontSize": { - "message": "Font Size" - }, - "font": { - "message": "Font" - }, - "fontStyle": { - "message": "Style" - }, - "normal": { - "message": "Normal" - }, - "bold": { - "message": "Bold" - }, - "italic": { - "message": "Italic" - }, - "bolditalic": { - "message": "Bold Italic" - }, - "oblique": { - "message": "Oblique" - }, - "boldoblique": { - "message": "Bold Oblique" - }, - "alignment": { - "message": "Alignment" - }, - "left": { - "message": "Left" - }, - "center": { - "message": "Centre" - }, - "right": { - "message": "Right" - }, - "text_here": { - "message": "Text Here" - }, - "smallCaps": { - "message": "Small Caps" - }, - "angle": { - "message": "Angle (°)" - }, - "arrow": { - "message": "Forward arrow" - }, - "backArrow": { - "message": "Backward arrow" - }, - "stop_drawing": { - "message": "Finish Drawing" - }, - "cropBoxSize": { - "message": "Crop Box Size" - }, - "format": { - "message": "Format" - }, - "width": { - "message": "Width" - }, - "rayCountLimit": { - "message": "Ray count limit" - }, - "transformation": { - "message": "TransformationBeta" - }, - "default": { - "message": "Default" - }, - "translation": { - "message": "Translation" - }, - "xTranslation": { - "message": "X Translation" - }, - "yTranslation": { - "message": "Y Translation" - }, - "rotation": { - "message": "Rotation" - }, - "scaling": { - "message": "Scaling" - }, - "beam_warning": { - "message": "Image detection may not work with divergent/random beams." - }, - "image_detection_warning": { - "message": "This tool does not support image detection." - }, - "non_simulateColors_warning": { - "message": "This tool only works when \"Simulate Color\" is on." - }, - "brightness_note_popover": { - "message": "

Only effective if 'Ray Density' is high enough.

To control the numbers of rays emitted, please adjust the global 'Ray Density' slider instead.

" - }, - "refIndex_note_popover": { - "message": "

*Relative if inside another glass

If this object is to be simulated with (absolute) refractive index n₁, but is placed inside another glass with refractive index n₀, then you should set the refractive index to n₁/n₀ here. In more complicated cases that several glasses overlap together, the effective reflective index of the overlapping region equals the product of the reflective indices of individual ones.

" - }, - "stepSize_note_popover": { - "message": "

Step size of Euler's method for solving the eikonal ray equation - see 'step' function and documentation inside the 'CircleGrinGlass.js' file, for more information.

" - }, - "eps_CircleGrinGlass_note_popover": { - "message": "

Units - [length]^2.

This numerical tolerance is used in the functions 'isOutsideGlass', 'isInsideGlass' and 'isOnBoundary', inside the 'CircleGrinGlass.js' file.

" - }, - "eps_GrinGlass_note_popover": { - "message": "

Units - [length].

This numerical tolerance is used in the functions 'isOnBoundary' and 'countIntersections', inside the 'GrinGlass.js' file.

" - }, - "cauchyCoeff": { - "message": "Cauchy coefficient" - }, - "transRatio": { - "message": "Transmission Ratio" - }, - "applytoall": { - "message": "Apply to All" - }, - "duplicate": { - "message": "Duplicate" - }, - "delete": { - "message": "Delete" - }, - "unselect": { - "message": "Unselect" - }, - "unselect_popover": { - "message": "Unselect this object (Right-click on blank space has the same function.)" - }, - "showadvanced": { - "message": "More options..." - }, - "processing": { - "message": "Processing... Click here to stop." - }, - "contribute": { - "message": "Contribute" - }, - "github": { - "message": "GitHub" - }, - "about": { - "message": "About" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "message": "Help us translate this app" - }, - "translated": { - "message": "translated" - }, - "undo_popover": { - "message": "Undo last action. (Ctrl+Z)" - }, - "redo_popover": { - "message": "Redo last action. (Ctrl+Y)" - }, - "reset_popover": { - "message": "Reset all changes." - }, - "save_popover": { - "message": "Save the current scene as a file." - }, - "open_popover": { - "message": "Open an existing file or background image. The background image will be shown from the coordinate origin. (Or drop the file)" - }, - "get_link_popover": { - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "message": "The URL is too long that it may not work on some platforms. You may need to use \"Save\" and share the file instead." - }, - "export_svg_warning": { - "message": "Export to SVG: Color mixtures and relative refractive indices below 1 are not supported." - }, - "export_ray_count_warning": { - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "message": "Go to the Gallery webpage to load an example." - }, - "tool_SingleRay_popover": { - "message": "A single ray of light defined by two points. (Drag or Click to create. The first point is the source, shooting toward the second point.)" - }, - "tool_Beam_popover": { - "message": "A parallel or divergent beam of rays emerges from a line segment, with density controlled by the 'Ray density' slider. (Drag or click to create.)" - }, - "tool_PointSource_popover": { - "message": "Rays emerge from a single point, with number controlled by the 'Ray density' slider. (Click to create.)" - }, - "tool_AngleSource_popover": { - "message": "Point source with a given emission angle." - }, - "tool_Mirror_popover": { - "message": "Simulate the reflection of light on a mirror. (Drag or click to create.)" - }, - "tool_ArcMirror_popover": { - "message": "A mirror whose shape is part of a circle, which is defined by three points. (Drag or click to create. The first 2 points define the gap between arc's edges, the last point defines the arc's size.)" - }, - "tool_ParabolicMirror_popover": { - "message": "A mirror whose shape is a parabola, which is defined by three points. (Drag or click to create.)" - }, - "tool_CustomMirror_popover": { - "message": "A mirror whose shape is defined by a custom equation y = f(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0). (Drag or click to create.)" - }, - "tool_BeamSplitter_popover": { - "message": "A mirror that transmits a percentage of incoming light. (Drag or click to create.)" - }, - "tool_IdealMirror_popover": { - "message": "The idealized 'curved' mirror which obeys exactly the mirror equation (1/p + 1/q = 1/f). The focal length can be set directly. (Drag or click to create.)" - }, - "tool_PlaneGlass_popover": { - "message": "Simulate the refraction and reflection of light on a surface. (Drag or click to create.)" - }, - "tool_CircleGlass_popover": { - "message": "Glass with a circle shape, defined by its center and a point on the surface. (Drag or click to create.)" - }, - "tool_CircleGrinGlass_popover": { - "message": "Glass with a custom refractive index function n(x,y) and a circular boundary. (Drag or click to create.)" - }, - "tool_Glass_popover": { - "message": "Glass with any shapes constructed from line segments and circular arcs. (Click to create a segment, drag to create an arc, click on the starting point when finish drawing.)" - }, - "tool_GrinGlass_popover": { - "message": "Glass with a custom refractive index function n(x,y) and a polygonal boundary. WARNING: Only simple polygons are supported, otherwise the behavior is unpredictable. (Click to create a segment, click on the starting point when finish drawing.)" - }, - "tool_IdealLens_popover": { - "message": "An ideal lens which obeys exactly the thin lens equation (1/p + 1/q = 1/f). The focal length can be set directly. (Drag or click to create.)" - }, - "tool_SphericalLens_popover": { - "message": "A spherical lens. (Click to create.)" - }, - "tool_CustomGlass_popover": { - "message": "Glass with the shape defined by a custom inequality f(x) < y < g(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0). (Drag or click to create.)" - }, - "tool_Blocker_popover": { - "message": "A line-segment light blocker which absorbs the incident rays. (Drag or click to create.)" - }, - "tool_Aperture_popover": { - "message": "A pair of light blockers which absorbs the incident rays. The size of the hole can be adjusted symmetrically. (Drag or click the two endpoints to create.)" - }, - "tool_CircleBlocker_popover": { - "message": "A circle light blocker which absorbs the incident rays. (Drag or click to create.)" - }, - "tool_DiffractionGrating_popover": { - "message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)" - }, - "tool_Ruler_popover": { - "message": "A ruler from a point for zero and another point. (Drag or click to create.)" - }, - "tool_Protractor_popover": { - "message": "A protractor defined from the center and another point for the zero direction. The scale is in degrees. (Drag or click to create.)" - }, - "tool_Detector_popover": { - "message": "A tool for measuring the rate of energy flow (P), the rate of perpendicular momentum flow (F⊥), and the rate of parallel momentum flow (F∥) through a line segment. (Drag or click to create the line segment.) The units are arbitrary." - }, - "tool_Detector_info_popover": { - "message": "" - }, - "tool_TextLabel_popover": { - "message": "A text label." - }, - "tool_LineArrow_popover": { - "message": "A line segment or arrow. (Drag or click to create.)" - }, - "tool_Drawing_popover": { - "message": "A freehand drawing tool. (Drag to draw.)" - }, - "tool__popover": { - "message": "Drag to move the view. (Mouse right button drag has the same function.)" - }, - "mode_rays_popover": { - "message": "Show the rays. When the 'Ray density' is high, they appear to be continuous." - }, - "mode_extended_popover": { - "message": "Show both the rays and its extension. Orange indicates backward extensions, and gray indicates forward ones.
When 'Simulate Colors' is on, they are shown in source colors and distinguished by dashing instead." - }, - "mode_images_popover": { - "message": "Show the position of all images. Yellow points indicate real images, orange indicates virtual images, and gray (none in this picture) indicates virtual objects. Note that some images cannot be detected if 'Ray density' is not high enough.
When 'Simulate Colors' is on, they are shown in source colors and distinguished by dot sizes instead." - }, - "mode_observer_popover": { - "message": "Simulate the rays and images seen from some position. The blue circle is the observer. Any rays crossing it are considered to be 'observed'. The observer does not know where the rays actually begin, but may think they begin at some point(s) if they intersect there. The rays are shown in blue, and the points in yellow (real) or orange (virtual). (Drag the big blue dot to move the observer.)
When 'Simulate Colors' is on, they are shown in source colors instead." - }, - "simulateColors_popover": { - "message": "Simulate colors (wavelengths) of light sources, mixture of colors, color filtering of blockers and mirrors, and chromatic dispersion of glasses. You can set those parameters for those objects when selected. To simulate color spectra, overlap rays with different wavelengths. The colors shown on the screen are only rough approximations, and can be very inaccurate when 'Ray density' is too high or too low." - }, - "rayDensity_popover": { - "message": "Determines the number of rays to be emitted by beams and point sources. This also affects the accuracy of image detection and color rendering." - }, - "showGrid_popover": { - "message": "Defines the visibility of the background grid." - }, - "grid_popover": { - "message": "Defines whether to snap to grid." - }, - "lockObjs_popover": { - "message": "Defines whether the objects can be moved or not." - }, - "zoom_popover": { - "message": "Zoom the view with percentage." - }, - "help_popover": { - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "message": "Show help popups" - }, - "show_help_popups_popover": { - "message": "Defines whether to show help popups when hovering over buttons. (Reload the page to take effect.)" - }, - "show_json_editor": { - "message": "Show JSON editorBeta" - }, - "show_json_editor_popover": { - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "message": "Show status box" - }, - "show_status_popover": { - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "message": "Grid Size" - }, - "observer_size": { - "message": "Observer Size" - }, - "language": { - "message": "Language" - }, - "close": { - "message": "Close" - }, - "advanced_help": { - "message": "For advanced help, see the help icon in the lower-right corner." - }, - "ray_count": { - "message": "Number of ray segments: " - }, - "total_truncation": { - "message": "Truncated brightness: " - }, - "brightness_scale": { - "message": "Brightness Scale: " - }, - "time_elapsed": { - "message": "Time elapsed (ms): " - }, - "force_stopped": { - "message": "Force stopped." - }, - "mouse_coordinates": { - "message": "Mouse coordinates: " - }, - "modules_tutorial": { - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "message": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior." - }, - "import_modules": { - "message": "Import Modules..." - }, - "import_modules_title": { - "message": "Import Modules" - }, - "modules_url": { - "message": "../modules/modules.html" - }, - "remove_module": { - "message": "Remove module" - }, - "module_conflict": { - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/en/gallery.json b/locales/en/gallery.json new file mode 100644 index 00000000..167fe87d --- /dev/null +++ b/locales/en/gallery.json @@ -0,0 +1,487 @@ +{ + "galleryPage": { + "title": "The Ray Optics Gallery", + "description": "This is a collection of simulations made using [the web app](/simulator), which can be used as interactive demos of optics. You are welcome to contribute new items. See [the contribution guide](/contributing/gallery) for more information. To report a mistake, please [open an issue on GitHub](/github/issues) or email [ray-optics@phydemo.app](/email).", + "categories": { + "title": "Categories", + "reflection": "Reflection", + "refraction": "Refraction", + "lens": "Lens", + "combinationOfLenses": "Combination of Lenses", + "grinOptics": "Gradient-index Optics", + "miscellaneous": "Miscellaneous" + }, + "contributors_one": "Contributor: {{contributors}}", + "contributors_other": "Contributors: {{contributors}}", + "openInSimulator": "Open in Simulator" + }, + "galleryData": { + "common": { + "warningthesequenceof": "Warning: The sequence of light appearing does not represent the actual speed of light - only the final image is meaningful." + }, + "imagesFormedByTwoMirrors": { + "title": "Images from Two Mirrors", + "description": "This simulation shows the images formed by two mirrors. The green \"L\" is the object. If the angle between the two mirrors is \\(\\frac{360^\\circ}{n}\\), then \\(n-1\\) virtual images (the orange L's) will be formed. You can drag the endpoint of the mirror to change the angle between them." + }, + "parabolicMirror": { + "title": "Parabolic Mirror", + "description": "This simulation demonstrates the focusing property of the parabolic mirror." + }, + "hyperbolicMirror": { + "title": "Hyperbolic mirror", + "description": "This is a demonstration of the reflection property of the hyperbolic mirror: Light rays traveling from one focus towards the hyperbolic mirror, will reflect away from the other focus.\n\nThe two foci of the hyperbola are aplanatic points (see [Aplanatic points](/gallery/aplanatic-points)).", + "theorangeraysareimag": "The orange rays are imaginary extended rays from the reflected yellow rays.\nThese imaginary rays converge at the other focus point.", + "pointlightsourceaton": "Point light source at one focus point" + }, + "retroreflectors": { + "title": "Retroreflectors", + "description": "This is a simulation of two types of retroreflectors:\n\n1. Corner retroreflector.\n2. Cat's eye retroreflector.", + "dragtorotatethebeam": "Drag to\nrotate the beam", + "catseyeretroreflecto": "Cat's eye retroreflector", + "cornerretroreflector": "Corner retroreflector" + }, + "periscope": { + "title": "Periscope", + "description": "This is a simulation of a periscope made from two flat mirrors and some light blockers.", + "observerseyenottosca": "Observer's eye (not to scale)" + }, + "newtonianTelescope": { + "title": "Newtonian Telescope", + "description": "This is a model of a Newtonian telescope with a Plössl ocular." + }, + "penroseUnilluminableRoom": { + "title": "Penrose unilluminable room", + "description": "The Penrose unilluminable room is constructed from elliptic, circular, and linear mirrors. It has the interesting property that a point source (green) within the room will not shine the entire room, no matter where you put it. You can drag the green point to move the source.", + "nomatterwhereyouputt": "No matter where you put the point source, it will not shine the entire room.\nWarning: Due to numerical error, it may still shine after some time." + }, + "opticalCavity": { + "title": "Two-mirror optical cavity", + "description": "This is a simulation of rays inside an optical cavity with two mirrors. Given the length of the cavity is \\(d\\), and the radius of curvature of its mirrors is \\(R_1\\) and \\(R_2\\) respectively (with the convention that \\(R>0\\) for a concave mirror), then the optical cavity is stable (meaning that for each ray that emanates from one of the mirrors towards the other mirror, a non-divergent trajectory is guaranteed for sufficiently high mirrors), if and only if \\(0\\leq (1-\\frac {d}{R_1})(1-\\frac {d}{R_2})\\leq 1\\). In this simulation we assume that the mirrors are ideal curved mirrors, meaning that \\(f=\\frac{R}{2}\\), rendering the previous stability condition to \\(0\\leq (1-\\frac {d}{2f_1})(1-\\frac {d}{2f_2})\\leq 1\\). [Here](/gallery/resonator) is a similar simulation with spherical mirrors, where the first stability condition holds in the paraxial approximation.", + "clickholdleftmouseto": "Click + hold left mouse\nto move the ray", + "dragtomovetheidealmi": "Drag to move\nthe ideal mirror", + "d400intheresonatorsb": "d = 400 in the resonators below", + "confocalresonator": "Confocal resonator", + "concentricresonator": "Concentric resonator", + "concaveconvexresonat": "Concave-convex resonator", + "planoconcaveresonato": "Plano-concave resonator" + }, + "resonator": { + "title": "Plano-concave resonator", + "description": "This is a demonstration of a plano-concave resonator. If the distance between the mirrors is greater than the radius of curvature, the resonator is unstable. If the distance between the mirrors is less than or equal to the radius of curvature, a stable resonator mode is formed.", + "flatmirror": "Flat mirror", + "sphericalconcavemirr": "Spherical concave mirror", + "unstableresonator": "Unstable resonator", + "stableresonator": "Stable resonator" + }, + "mazeSolution": { + "title": "Maze solution", + "description": "This is a simulation of a light ray originating inside a maze and reflected repeatedly by the walls. The larger and smaller red squares inside the maze (seen in the screenshot below) represent the origin and the initial direction of the light ray, respectively. For some initial orientations of the light ray, it exits the maze, and thus by retracing the path of the ray a solution to the maze can in principle be calculated.", + "controltherayorigina": "Control the ray origin and initial direction by\ndragging the top and bottom markers (respectively).", + "notethatthesimulatio": "Note that the simulation processing is finished only once\nthe processing message at the bottom left corner disappears.", + "mazeexit": "Maze exit" + }, + "specularAndDiffuseReflection": { + "title": "Specular and Diffuse Reflections", + "description": "Identical beams shine on a smooth surface and a rough surface, illustrating the difference between specular and diffuse reflections.", + "specular": "Specular", + "diffuse": "Diffuse" + }, + "chaffCountermeasure": { + "title": "Chaff countermeasure", + "description": "This is a qualitative simulation of the effect that the chaff countermeasure has on a radar (ignoring diffraction effects).", + "plane": "Plane", + "radar": "Radar", + "chaff": "Chaff", + "selectthechafftochan": "Select the chaff to change the number (N) and the length (L) of chaff pieces." + }, + "causticsFromAReflectiveSphere": { + "title": "Caustics from a Reflective Sphere", + "description": "A reflective integrating sphere (not scattering) with an entrance hole. Can also be the reflections inside a liquid drop (like a raindrop). Beautiful patterns emerge where the caustics develop by moving the point source around.", + "movethepointsourcear": "Move the point source around\nto watch the caustics and nodes \nwithin the integrating sphere transform.\nChange size and position of the blockers, \nand the opening size of the sphere\nto see more effects." + }, + "theMirascope": { + "title": "The Mirascope", + "description": "A **mirascope** is a fascinating optical illusion device that uses two opposing parabolic mirrors to create the illusion of a three-dimensional floating image. The device consists of:\n1. **Two Parabolic Mirrors** of the exact same size, with one mirror facing upward and the other facing downward, forming a clam-like structure. The mirrors are designed to focus light at a specific point. The top mirror has a hole at its vertex to allow the light to enter the device.\n2. **A Small Object**: Placed inside the mirascope, typically near the focal point of the top mirror that is very close to the vertex of the bottom mirror.\n\nWhen light from the object reflects between the mirrors, it is redirected in such a way that it appears as a lifelike, three-dimensional image floating above the surface of the mirascope. The illusion is so convincing that people often try to touch the image, only to find there's nothing there.\n\nMirascopes are popular in science demonstrations, toys, and novelty items to illustrate the principles of optics, reflection, and the behavior of light.", + "object1": "Object", + "realimage1": "Real image" + }, + "reflect": { + "title": "Reflection and Refraction", + "description": "This simulation shows the reflection and refraction at a surface." + }, + "internalReflection": { + "title": "Internal Reflection", + "description": "This simulation shows the refraction and internal reflection at a surface." + }, + "prisms": { + "title": "Prisms", + "description": "This simulation demonstrates the right-angle prism, the Porro prism, the rhomboid prism, the Dove prism, and the pentaprism.", + "rhomboid": "rhomboid", + "rightangle": "right-angle", + "porro": "Porro", + "dove": "Dove", + "pentaprism": "pentaprism" + }, + "beamDirectors": { + "title": "Beam Directors", + "description": "This is a simulation of a regular and a Fresnel biprism. A biprism can direct an incoming collimated beam into two directions, depending on the apex angle.", + "thisfresnelbiprismwa": "This fresnel biprism was made from the above biprism.\nYou can select the biprism and adjust the N_silce parameter.", + "fresnelbiprism": "Fresnel biprism", + "biprism": "Biprism" + }, + "apparentDepth": { + "title": "Apparent Depth", + "description": "When you look at an object underwater from the air, the depth of the object appears to be smaller than its actual depth. This phenomenon is due to the reflection of light, and is demonstrated in this simulation. The apparent depth depends on the position of the observer, which can be demonstrated by dragging the blue circle.", + "observedimageorange": "Observed image (orange)", + "observer": "Observer", + "objectunderwatergree": "Object underwater (green)" + }, + "bendedPencil": { + "title": "Bent Pencil", + "description": "This is a simulation of the image perceived with our eyes, when looking from above on a partially submerged pencil in a glass of water. The discontinuity of the refractive index between air and water causes the pencil to appear both broken and bent. However, in this simulation, the bending is more pronounced. You can check the [Broken Pencil](/gallery/broken-pencil) simulation where the breaking of the pencil is more pronounced.", + "bentpencilyellowimag": "bent pencil (yellow)\nimage on retina", + "dielectricmaterial": "dielectric material", + "originalpencilgreen": "original pencil (green)", + "observerseye": "observer's eye", + "ignoretheorangesquar": "Ignore the orange squares!" + }, + "brokenPencil": { + "title": "Broken Pencil", + "description": "This is a simulation of the image perceived with our eyes, when looking from the side at a partially submerged pencil in a glass of water. The discontinuity of the refractive index between air and water causes the pencil to appear both broken and bent. However, in this simulation, the breaking is more pronounced. You can check the [Bent Pencil](/gallery/bended-pencil) simulation where the bending of the pencil is more pronounced.", + "brokenpencilyellowim": "broken pencil (yellow)\nimage on retina" + }, + "chromaticDispersion": { + "title": "Chromatic dispersion", + "description": "This simulation demonstrates chromatic dispersion using a white-colored beam and a triangular prism. Here the white color is formed by mixing red, orange, yellow, green, cyan, blue, and violet colors.", + "dragheretoadjustbeam": "Drag here to\nadjust beam width", + "dragheretorotatethep": "Drag here to\nrotate the prism" + }, + "rainbows": { + "title": "Rainbows", + "description": "This simulation demonstrates the formation of the primary rainbow, the secondary rainbow, and Alexandar's dark band. Here the spectrum of the sunlight is approximated by mixing red, orange, yellow, green, cyan, blue, and violet colors. The outgoing rays for the primary/secondary rainbow are due to one/two internal reflections within the raindrop (you can see this by setting Ray Density to a low number and dragging the raindrop). Note that these are not total internal reflections, so the intensities of the outgoing rays are much lower than the incoming rays. Since the [minimum deviation angles](/gallery/minimum-deviation-angle) depend on the wavelength, different colors accumulate at different angles. Hence the colors in the rainbows are produced. Away from the minimum angles, the rays do not accumulate, so all colors are weak and mixed together, producing the dim white (or \"gray\") color at the angles just outside the two rainbows. On the other hand, no rays go to the angle between the two rainbows, forming Alexandar's dark band.", + "thesearethecolorspro": "These are the colors produced from a single raindrop.\nThe final rainbows we see are due to an enormous number of raindrops in the sky,\neach of which gives a single color (at the corresponding angle) to the observer.", + "secondaryrainbow": "Secondary rainbow", + "alexandersdarkband": "Alexander's dark band", + "raindrop": "Raindrop", + "primaryrainbow": "Primary rainbow", + "sunlight": "Sunlight" + }, + "minimumDeviationAngle": { + "title": "Minimum deviation angle", + "description": "The definition of the deviation angle of a ray hitting an optical element depends on the context - in the screenshot below you can see its definition for a triangular and a spherical prism. In the examples inside this simulation, the deviation angle as a function of the incidence angle of the ray entering the optical element, has a local minimum at a deviation angle which is called the \"minimum deviation angle\". This local minimum can explain optical phenomena such as [rainbows](/gallery/rainbows) and halos - due to this local minimum, the deviated rays accumulate at specific directions, creating \"optical caustics\" (as seen in example C inside the simulation) which we perceive as rainbows/halos.", + "inexamplesaandbbyrot": "In examples A and B, by rotating the prisms between points A1 to A2 and B1 to B2, thereby changing the\nincidence angle of the ray entering into the optical element, you can clearly observe that a minimum\ndeviation angle is achieved somewhere between the pair of points.\n(in example A the deviation angle is measured relative to a horizontal axis, whereas in example B\nit is measured relative to the vertical axis).\n\nNow zoom into example C (using the simulation zoom), and expand the two beams (red and purple, and\ntheir intersection looks pink. This is effectively the same as rotating the spherical prism in\nexample B, thereby changing the incidence angle of the entering ray) and observe that from point\nC1 to C2 the backward exiting rays accumulate down towards two distinct red and purple\nrays (\"optical caustics\") - the minimum deviation angle is achieved around point C2, and depends on\nthe light wavelength (color). Then, when expanding the two beams from point C2 to C3, the\nbackward exiting rays reverse their direction upward.", + "examplea": "Example - A", + "examplec": "Example - C", + "exampleb": "Example - B", + "dragtorotate": "Drag to rotate", + "dragtoadjustbeamwidt": "Drag to adjust beam widths", + "usethebuiltinzoomtob": "Use the built-in zoom to better interact with the simulation", + "deviationangle": "Deviation angle", + "incidenceangle": "Incidence angle" + }, + "aplanaticPoints": { + "title": "Aplanatic points", + "description": "Aplanatic points of an optical system are special points on its optical axis, such that \"rays proceeding from one of them will all converge to, or seen to diverge from the other point\".\n\n- Ellipse: the two foci of the elliptical lens/mirror are aplanatic points, since light emitted from one focus will converge towards the other.\n- Sphere: a spherical lens has two aplanatic points, inside and outside the sphere - for more details see the simulation.\n- Hyperbola: the two foci of the [Hyperbolic mirror](/gallery/hyperbolic-mirror) simulation are also aplanatic points.\n\nGiven two points with horizontal coordinates \\(x_1\\) and \\(x_2\\), identical vertical coordinates, and given the refractive index outside and inside our optical element as \\(n_1\\) and \\(n_2\\) (respectively), for this two points to be aplanatic points, the boundary of our optical element must fulfill\\begin{equation}k_1 n_1 \\sqrt{ (x - x_1)^2 + y^2} + k_2 n_2 \\sqrt{ (x - x_2)^2 + y^2} = E\\end{equation}such that \\(k_i=1\\) or \\(-1\\) if the ray connecting \\(x_i\\) and the boundary of our optical element is real or imaginary, respectively, and \\(E\\) is a constant for which this equation has a non-trivial solution. This equation (which can be derived using Fermat's principle) is an equation of a Cartesian oval, of which the conic sections are special cases.", + "clickontheextendedra": "Click on the \"Extended rays\" button to verify that light emitted from the light source in the spherical lens (point A),\nwill diverge from another point on the optical axis outside the spherical lens (point B) without spherical aberration.\nPoints A and B are an example of aplanatic points of the sphere, for which (k1, k2, n1, n2, x1, x2, E)=(1, -1, 1.5, 1, 3 * 20, -4.5 * 20, 0) relative to the marked Y axis,\nwhere x1,x2 are the horizontal coordinates of points A,B respectively (each grid cell has dimensions of 20 by 20).\nIn a similar way, the foci of the ellipse (points C and D) are an example of aplanatic points of the ellipse, for which (k1, k2, n1, n2, E)=(1, 1, 1.5, 1.5, > 0)", + "sphericallens": "Spherical lens", + "ellipticallens": "Elliptical lens", + "yaxis": "Y axis" + }, + "concaveLens": { + "title": "Concave Lens", + "description": "This simulation shows a concave lens diverging a beam." + }, + "convexLens": { + "title": "Convex Lens", + "description": "This simulation shows a convex lens converging a beam." + }, + "lensImages": { + "title": "Lens Images", + "description": "This simulation shows the images of a beam and point sources produced by ideal lenses." + }, + "transverseAndLongitudinalMagnification": { + "title": "Transverse and longitudinal magnification", + "description": "This is a simulation of transverse and longitudinal magnification for an ideal lens with focal length \\(f\\). The transverse (also called linear) and the longitudinal magnification is \\(M_T=1-\\frac{u}{f}\\) and \\(M_L=\\frac{dv}{du}\\) respectively, where \\(u\\) and \\(v\\) is the distance of the object and the image from our ideal lens, respectively. Also, for an ideal lens \\(M_L=-(M_T)^2\\)", + "inthisexamplewehavey": "In this example we have y'_j - y'_k = M_T * (y_j - y_k), where j,k∈{0,1,2,3,4,5}.\nTherefore for example the tranverse magnification of the point object (x_0,y_0) is M_T = -3, and we can calculate - \n(x'_0 - x'_1)/(x_1 - x_0) ≈ -0.3699\n(x'_0 - x'_2)/(x_2 - x_0) ≈ -0.7297\n(x'_0 - x'_3)/(x_3 - x_0) ≈ -1.4211\n(x'_0 - x'_4)/(x_4 - x_0) ≈ -2.4545\n(x'_0 - x'_5)/(x_5 - x_0) = -5.4\n.\n.\n.\n(The ratio will converge to the longitudinal magnification: M_L = - (M_T)^2 = -9)", + "rightclickonarealobj": "Right click on a (real) object to see its coordinates.\nThe green squares are real point sources, while the yellow squares are image objects." + }, + "vanishingPoint": { + "title": "Vanishing point", + "description": "Some optical systems map infinite parallel lines, to lines on the image plane which meet at a single point, making an illusion that the parallel lines meet \"at infinity\". This single point is called the vanishing point.\n\nFor an optical system comprising an ideal lens with focal length \\(f\\), located on the \\(XY\\) plane, such that its optical axis coincides with the \\(X\\)(horizontal) axis and the lens coincides with the \\(Y\\) axis, the vanishing point for a line with a slope \\(m\\), located at \\(x<0\\), is given by the \\((x,y)\\) coordinates \\((f,m f)\\) .", + "youcanverifythatapai": "You can verify that a pair of parallel lines with slope - m, converge by the ideal lens to the coordinates (f,m∙f),\nby clicking the \"Grid\" button and noticing that each grid cell has dimensions of 20 by 20.\nYou can also verify how changing the ideal lens's focal length - f, effects the converging points (vanishing points).", + "thesepairofparallell": "These pair of parallel lines converge to point B", + "thesepairofparallell1": "These pair of parallel lines converge to point A", + "notethatthesepairsof": "Note that these pairs of parallel lines are not actually infinite." + }, + "monochromaticAberrations": { + "title": "Monochromatic aberrations", + "description": "This is a simulation of different monochromatic aberrations:\n\n1. Spherical aberration.\n2. Comma aberration.\n3. Defocus aberration.\n4. Field curvature aberration.", + "defocusaberration": "Defocus aberration", + "sphericalaberration": "Spherical aberration", + "screen": "Screen", + "fieldcurvatureaberra": "Field curvature aberration", + "commaaberration": "Comma aberration" + }, + "chromaticAberration": { + "title": "Chromatic aberration", + "description": "This simulation shows the chromatic aberration of a spherical lens. Here the white color is formed by mixing red, orange, yellow, green, cyan, blue, and violet colors. The focal length of red light is the largest, and that of violet light is the smallest.", + "dragtoadjustbeamwidt1": "Drag to adjust beam width" + }, + "hyperbolicLens": { + "title": "Hyperbolic lens", + "description": "This is a simulation and comparison between the hyperbolic and spherical lenses. Both lenses have identical focal lengths, but as opposed to the spherical lens, the hyperbolic lens can collimate a parallel beam of monochromatic light to a single point (neglecting the wave nature of light - i.e in the geometric optics approximation) without spherical aberrations.", + "thefocallengthofthis": "The focal length of this spherical lens (in the paraxial approximation) is:\nf=R/(n-1)=200/(1.5-1)=400", + "thefocallengthofthis1": "The focal length of this hyperbolic lens is:\nf = |C| ∙ sqrt(n^2 - 1) / (n - 1) = K ∙ sqrt(0.8) ∙ sqrt(1.5^2 - 1) / (1.5 - 1) = 400\nwhere the equation for this hyperbola is:\ny(x) = (a/K) - sqrt( ((x/K)^2 + (C/K)^2) / (n^2 - 1) )\n= 1.5 - sqrt( (0.8 + (x / 200)^2) / (1.5^2 - 1) )\nsuch that K is the conversion constant between the equation dimensions to the grid dimensions - for this hyperbolic lens K=200.\n(for example 0 0\\) and \\(\\alpha = \\arctan k\\) is a constant angle between the two tangents at the intersection point between the concentric logarithmic spiral and circle (as demonstrated in [this](https://en.wikipedia.org/wiki/Logarithmic_spiral#/media/File:Logspiral.gif) animation), is \\(n(r) ∝ \\frac{1}{r} \\) (this can be shown by writing the optical path in polar coordinates, and using Fermat's principle).", + "thecircularblockeris": "The circular blocker is in the center\nto avoid the refractive index singularity", + "dragtochangetheiniti": "Drag to change the\ninitial direction of the ray", + "youcanselectthegring": "You can select the GRIN glass and\nchange the numerical solver step size" + }, + "luneburgLens": { + "title": "Luneburg lens", + "description": "This is a simulation of a Luneburg lens, which is a spherical dielectric with refractive index \\(n(r) = \\sqrt{n_0-(\\frac{r}{R})^2} \\), where \\(n_0=2\\) is the refractive index in the center of the lens, \\(R=100\\) is the radius of the lens, and \\(r\\) is the radial distance from the center of the lens.\n\nThe top dielectric is composed of \\(N=20\\) concentric spherical lenses with radius \\(R_i=5(N+1-i)\\) and refractive index \\(n_i = \\sqrt{n_0-(\\frac{R_i}{R})^2} \\), where \\(i=1,...,N\\). However, since this simulator calculates the effective refractive index of an optical element by multiplying the element's numerical refractive index with the numerical refractive indices of the optical elements which are embedded within it, the numerical refractive index of the \\(i\\)th concentric spherical lens is given by \\(n_{i}^\\text{numerical}=\\frac{n_i}{n_{i-1}}\\).\n\nThe bottom dielectric is a gradient-index material with the refractive index \\(n(r)\\).", + "approximatedmultilay1": "Approximated multilayer Luneburg lens (You can select and change N, the number of layers.)", + "classicalluneburglen": "Classical Luneburg lens (You can select and change the numerical solver step size.)" + }, + "maxwellFisheyeLens": { + "title": "Maxwell fisheye lens", + "description": "This is a simulation of a Maxwell fish-eye lens, which is a spherical dielectric with refractive index \\(n(r) = \\frac{n_0}{1+(\\frac{r}{R})^2} \\), where \\(n_0=2\\) is the refractive index in the center of the lens, \\(R=100\\) is the radius of the lens, and \\(r\\) is the radial distance from the center of the lens.\n\nThe top dielectric is composed of \\(N=20\\) concentric spherical lenses with radius \\(R_i=5(N+1-i)\\) and refractive index \\(n_i = \\frac{n_0}{1+(\\frac{R_i}{R})^2} \\), where \\(i=1,...,N\\). However, since this simulator calculates the effective refractive index of an optical element by multiplying the element's numerical refractive index with the numerical refractive indices of the optical elements which are embedded within it, the numerical refractive index of the \\(i\\)th concentric spherical lens is given by \\(n_{i}^\\text{numerical}=\\frac{n_i}{n_{i-1}}\\).\n\nThe bottom dielectric is a gradient-index material with the refractive index \\(n(r)\\).", + "approximatedmultilay2": "Approximated multilayer Maxwell fisheye lens (You can select and change N, the number of layers.)", + "classicalmaxwellfish": "Classical Maxwell fisheye lens (You can select and change the numerical solver step size.)" + }, + "branchedFlow": { + "title": "Branched flow", + "description": "When light travels through a medium whose refractive index has random spatial fluctuations (with correlation length much larger than the wavelength of the light), a tree-like pattern called branched flow will appear. This simulation shows this phenomenon using a refractive index function which is a sum of several cosine functions with random-like amplitudes, wave vectors, and phases." + }, + "singleRayDemo": { + "title": "Single Ray demo", + "description": "This simulation demonstrates the reflection and refraction of a single ray." + }, + "sphericalLensAndMirror": { + "title": "Spherical Lens and Mirror", + "description": "This simulation shows a continuous beam passing through a spherical lens and a spherical mirror." + }, + "interrogationRoom": { + "title": "Interrogation room", + "description": "This is a simulation of a two-way mirror in an interrogation room. The observer in the dark room (ideally the dark room's interior is not emitting/reflecting light, as well as absorbing all the incoming light from the interrogation room) is able to see inside the interrogation room because the light created by the lamp in the interrogation room is scattered and received by the observer through the two-way mirror, whereas the suspect can only see inside the interrogation room as well as his/her and the lamp's reflections (since no light is received by the suspect from the dark room).", + "pressonallimagestose": "Press on \"All Images\" to see the location\nof the lamp's reflection, and the objects\nin the suspect's and observer's image plane", + "darkroom": "Dark room", + "twowaymirror": "Two-way mirror", + "lamp": "Lamp", + "interrogationroom": "Interrogation room", + "observerseyeris": "Observer's eyeris", + "suspectseyeris": "Suspect's eyeris", + "thelampobjectinthesu": "The lamp object in the suspect's image plane", + "thelampsreflectionin": "The lamp's reflection in the suspect's image plane", + "thelampsreflection": "The lamp's reflection", + "thelampobjectintheob": "The lamp object in the observer's image plane" + }, + "cameraObscura": { + "title": "Camera obscura", + "description": "This is a simulation of a Camera obscura. The observer in the dark room sees an inverted image of the objects outside, projected on the wall in front of him/her (without the use of an extra lens).", + "observer2": "Observer", + "objectsoutside": "Objects outside", + "darkroom1": "Dark room" + }, + "thePrincipleOfCameraImaging": { + "title": "The principle of camera imaging", + "description": "This template provides an interactive approach to learning the principles of camera imaging, covering essential topics such as focal length, aperture, sensor sensitivity, and background blur, making it useful for both students and enthusiasts.", + "camera": "Camera", + "cmos": "CMOS" + }, + "nlSimulation": { + "title": "NL Binoculars", + "description": "This simulation shows a rough sketch of Swarovski NL binoculars." + }, + "einsteinRingRefocusedToSingleImageViaEyepiece": { + "title": "Einstein Ring refocused to Single Image via Eyepiece", + "description": "This is a model of an eyepiece/lens that could be used on any scientific telescope which will reverse the \"halo\" and focus an Einstein ring back into its original form while scattering the light of any star or massive object used to create the ring." + }, + "blackCatBecomesWhite": { + "title": "\"Black cat becomes white\" demo", + "description": "\"Black cat becomes white\" is a popular science demo in which some part of a figure disappears when put in water. It is made with the following steps:\n\n1. Draw a figure (e.g. a black cat) on a piece of paper.\n2. Put the paper in a plastic zip-lock bag.\n3. Draw part of the figure (e.g. the border of the cat) or some other figure on the plastic surface. When put in water, the figure drawn on the paper disappears, but not the part drawn on the plastic surface.\n\nThis simulation explains how it works.", + "whenthebagisunderwat": "When the bag is underwater, the light from the paper does not reach the eyes,\nso we only see the figure drawn on the plastic surface.", + "lightfromtheplastics": "Light from the plastic surface", + "lightfromthepaper": "Light from the paper", + "eyes": "Eyes", + "dragtomovethebagouto": "Drag to move the bag out of water" + }, + "dichroicRbgSplitterAndCombiner": { + "title": "Dichroic RGB Splitter & Combiner", + "description": "This simulation demonstrates the splitting and combination of RGB beams using dichroic mirrors.", + "rgbcomponentsplitter": "RGB Component Splitter & Combiner", + "lightsource": "Light Source", + "dichroiccube": "Dichroic Cube", + "beamcombiner": "Beam Combiner" + }, + "ganBasedLcdPixel": { + "title": "LCD Pixel", + "description": "This is a model of an LCD pixel. It simulates how new microled display layers function and how our eyes perceive the pixel.", + "pixelsaresosmallthel": "Pixels are so small the light\nappears to be mixed to our eyes", + "changetherateoftrans": "Change the Rate of Transmission\nTo Create Any RGB Value", + "blueledbacklight": "Blue LED Backlight", + "yellowphosphor": "Yellow Phosphor", + "liquidcrystal": "Liquid Crystal", + "lightfilters": "Light Filters", + "pixelasvisibletoview": "Pixel as Visible to Viewer", + "notpartoflcddisplay": "Not part of LCD display" + }, + "concaveMirrorWearableDisplay": { + "title": "Concave Mirror Wearable Display", + "description": "A simple wearable display. A lot of designs use two mirrors and a positive lens, but this is a one-optical-element version. The scale is approximately 5:1mm.\n\nCC0: This work has been marked as dedicated to the public domain.", + "tft09display": "TFT 0.9\" display", + "concavemirror": "concave mirror", + "eye1": "eye", + "nose": "nose", + "pointsourcetomeasure": "point source to measure radius", + "t15readingglasses": "+1.5 reading glasses" + }, + "reflectingMonochromator": { + "title": "Reflecting Monochromator", + "description": "This is a simulation of a reflecting monochromator, which uses a reflective diffraction grating and a slit at the focus to get narrow band wavelengths from composite light.", + "reflectingmonochroma": "Reflecting Monochromator", + "rotatediffractiongra": "Rotate Diffraction Grating \nto get narrow band \nwavelengths from \ncomposite light", + "exitslitmonochromati": "Exit Slit\n\nMonochromatic Light" + }, + "solarEclipses": { + "title": "Solar Eclipses", + "description": "This simulation demonstrates the different types of solar eclipses. The top-right diagram depicts a solar eclipse where the Moon's shadow covers the Sun, resulting in a total eclipse at the center and a partial eclipse in surrounding areas. The bottom-right diagram illustrates an annular eclipse where the Moon is too far from Earth to completely cover the Sun, leaving a bright ring at the center (in this 2D simulator, the \"ring\" is demonstrated by sunlight coming only from the upper and the lower part of the sun) and also a partial eclipse in surrounding areas.", + "nottoscale": "(Not to scale)", + "sun": "Sun", + "moon": "Moon", + "partialeclipse": "Partial eclipse", + "annulareclipse": "Annular eclipse", + "earth": "Earth", + "totaleclipse": "Total eclipse" + }, + "moduleExampleBasics": { + "title": "Module Example - Basics", + "thistextisinexamplem": "This text is in ExampleModule.", + "thistextisalsoinexam": "This text is also in ExampleModule.", + "thistextisnotinamodu": "This text is not in a module.", + "thistextisalsonotina": "This text is also not in a module." + }, + "moduleExampleParameters": { + "title": "Module Example - Parameters", + "thismodulehastwopara": "This module has two parameters: n=`n` and theta=`theta`.\nYou can select and drag the sliders to adjust them.", + "thesizeofthistextosc": "The size of this text oscillates as a function of theta." + }, + "moduleExampleControlPoints": { + "title": "Module Example - Control points", + "hereisthefirstdragga": "↙Here is the first (draggable) control point of the module", + "hereistheseconddragg": "↙Here is the second (draggable) control point of the module", + "hereisthemidpoint": "↙Here is the midpoint" + }, + "moduleExampleArraysAndConditionals": { + "title": "Module Example - Arrays and conditionals", + "a1darrayii": "A 1D array: i=`i`", + "thistextisshownonlyw": "This text is shown only when n>5" + }, + "moduleExampleCustomEquation": { + "title": "Module Example - Custom equation", + "amirrorofshapeycos2p": "A mirror of shape y=cos(2 pi x + `phi`)" + }, + "moduleExampleShapeParametrization": { + "title": "Module Example - Shape parametrization", + "alensdefinedbydr1r2": "A lens defined by d, R_1, R_2", + "alensdefinedbydffdbf": "A lens defined by d, FFD, BFD" + } + } +} \ No newline at end of file diff --git a/locales/en/main.json b/locales/en/main.json new file mode 100644 index 00000000..3c899f69 --- /dev/null +++ b/locales/en/main.json @@ -0,0 +1,231 @@ +{ + "meta": { + "languageName": "English", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "Ray Optics Simulation", + "shortName": "Ray Optics", + "description": "A free, open-source web app for creating and simulating 2D geometric optical scenes." + }, + "pages": { + "simulator": "Simulator", + "home": "Home", + "gallery": "Gallery", + "modules": "Modules", + "about": "About", + "github": "GitHub" + }, + "homePage": { + "description": "Create & simulate 2D geometric optical scenes interactively.\nTotally free and web-based. Source code is [available on GitHub](/github).", + "launchSimulator": "Launch Simulator" + }, + "tools": { + "title": "Tools", + "categories": { + "lightSource": "Light Source", + "mirror": "Mirror", + "glass": "Glass", + "blocker": "Blocker", + "other": "Other" + }, + "common": { + "clickInstruction": "Click to create.", + "lineInstruction": "Drag or click to create.", + "circleInstruction": "Drag or click to create, first the center, then the circumference." + }, + "SingleRay": { + "title": "Single ray", + "description": "A single ray of light defined by two points.", + "instruction": "Drag or Click to create, first the source, then the direction." + }, + "Beam": { + "title": "Beam", + "description": "A parallel or divergent beam of rays emerges from a line segment, with density controlled by the 'Ray density' slider." + }, + "PointSource": { + "title": "Point source", + "description": "Rays emerge from a single point, with number controlled by the 'Ray density' slider." + }, + "AngleSource": { + "instruction": "Drag or Click to create, first the source, then the direction.", + "description": "Point source with a given emission angle." + }, + "Mirror": { + "title": "Segment", + "description": "Simulate the reflection of light on a mirror." + }, + "otherMirror": { + "title": "Curved", + "description": "A mirror whose shape is curved. Can be circular, parabolic, or defined by a custom equation y = f(x)." + }, + "ArcMirror": { + "title": "Circular Arc", + "description": "A mirror whose shape is part of a circle, which is defined by three points.", + "instruction": "Drag or click the two endpoints to create, then click a third point on the arc to define the curvature." + }, + "ParabolicMirror": { + "title": "Parabolic", + "description": "A mirror whose shape is a parabola, which is defined by three points.", + "instruction": "Drag or click the two endpoints to create, then click the vertex." + }, + "CustomMirror": { + "title": "Custom Equation", + "description": "A mirror whose shape is defined by a custom equation y = f(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0)." + }, + "IdealMirror": { + "title": "Ideal curved mirror", + "description": "The idealized 'curved' mirror which obeys exactly the mirror equation (1/p + 1/q = 1/f). The focal length can be set directly." + }, + "BeamSplitter": { + "title": "Beam Splitter", + "description": "A mirror that transmits a percentage of incoming light." + }, + "PlaneGlass": { + "title": "Half-plane", + "description": "Simulate the refraction and reflection of light on a surface.", + "instruction": "Drag or click two points on the surface to create." + }, + "otherGlass": { + "title": "Other shapes", + "description": "Glass with any shapes constructed from line segments and circular arcs, or shapes defined by a custom inequality f(x) < y < g(x)." + }, + "CircleGlass": { + "title": "Circle", + "description": "Glass with a circle shape, defined by its center and a point on the surface." + }, + "Glass": { + "title": "Polygon / Circular Arcs", + "description": "Glass with any shapes constructed from line segments and circular arcs.", + "instruction": "Click to create a segment, drag to create an arc, click on the starting point when finish drawing." + }, + "CustomGlass": { + "title": "Custom Equation", + "description": "Glass with the shape defined by a custom inequality f(x) < y < g(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0)." + }, + "IdealLens": { + "title": "Ideal Lens", + "description": "An ideal lens which obeys exactly the thin lens equation (1/p + 1/q = 1/f). The focal length can be set directly." + }, + "SphericalLens": { + "title": "Spherical Lens", + "description": "A spherical lens, whose shape can be defined using various parameters." + }, + "CircleGrinGlass": { + "title": "Gradient-index circle", + "description": "Glass with a custom refractive index function n(x,y) and a circular boundary." + }, + "GrinGlass": { + "title": "Gradient-index polygon", + "description": "Glass with a custom refractive index function n(x,y) and a polygonal boundary.", + "instruction": "Click to create a segment, click on the starting point when finish drawing.", + "warning": "WARNING: Only simple polygons are supported, otherwise the behavior is unpredictable." + }, + "otherGrinGlass": { + "title": "Gradient-index glass", + "description": "Material with a custom refractive index function n(x,y)." + }, + "Blocker": { + "title": "Line Blocker", + "description": "A line-segment light blocker which absorbs the incident rays." + }, + "CircleBlocker": { + "title": "Circle Blocker", + "description": "A circle light blocker which absorbs the incident rays." + }, + "Aperture": { + "title": "Aperture", + "description": "A pair of light blockers which absorbs the incident rays. The size of the hole can be adjusted symmetrically.", + "instruction": "Drag or click the two endpoints to create." + }, + "DiffractionGrating": { + "title": "Diffraction Grating", + "description": "A diffraction grating that splits light at an angle depending on wavelength.", + "warning": "Warning: The intensities of diffracted rays may not be accurate." + }, + "Ruler": { + "title": "Ruler", + "description": "A ruler from a point for zero and another point." + }, + "Protractor": { + "title": "Protractor", + "description": "A protractor defined from the center and another point for the zero direction. The scale is in degrees." + }, + "Detector": { + "title": "Detector", + "description": "A tool for measuring the rate of energy flow (P), the rate of perpendicular momentum flow (F⊥), and the rate of parallel momentum flow (F∥) through a line segment. The units are arbitrary." + }, + "TextLabel": { + "title": "Text", + "description": "A text label." + }, + "LineArrow": { + "title": "Line / Arrow", + "description": "A line segment or arrow." + }, + "Drawing": { + "title": "Drawing", + "description": "A freehand drawing tool.", + "instruction": "Drag to draw." + }, + "moveView": { + "title": "Move view", + "description": "Drag to move the view. (Mouse right button drag has the same function.)" + }, + "modules": { + "import": "Import Modules...", + "remove": "Remove module" + } + }, + "view": { + "title": "View", + "rays": { + "title": "Rays", + "description": "Show the rays. When the 'Ray density' is high, they appear to be continuous." + }, + "extended": { + "title": "Extended rays", + "description": "Show both the rays and its extension. Orange indicates backward extensions, and gray indicates forward ones.", + "simulateColorsNote": "When 'Simulate Colors' is on, they are shown in source colors and distinguished by dashing instead." + }, + "images": { + "title": "All Images", + "description": "Show the position of all images. Yellow points indicate real images, orange indicates virtual images, and gray (none in this picture) indicates virtual objects. Note that some images cannot be detected if 'Ray density' is not high enough.", + "simulateColorsNote": "When 'Simulate Colors' is on, they are shown in source colors and distinguished by dot sizes instead." + }, + "observer": { + "title": "Seen by Observer", + "description": "Simulate the rays and images seen from some position. The blue circle is the observer. Any rays crossing it are considered to be 'observed'. The observer does not know where the rays actually begin, but may think they begin at some point(s) if they intersect there. The rays are shown in blue, and the points in yellow (real) or orange (virtual).", + "simulateColorsNote": "When 'Simulate Colors' is on, they are shown in source colors instead.", + "instruction": "Drag the big blue dot to move the observer." + } + }, + "simulateColors": { + "title": "Simulate Colors", + "description": "Simulate colors (wavelengths) of light sources, mixture of colors, color filtering of blockers and mirrors, and chromatic dispersion of glasses.", + "instruction": "You can set those parameters for those objects when selected. To simulate color spectra, overlap rays with different wavelengths.", + "warning": "The colors shown on the screen are only rough approximations, and can be very inaccurate when 'Ray density' is too high or too low." + }, + "aboutPage": { + "description": "This project, including the gallery contents, is licensed under the [Apache License 2.0](/license), and is officially hosted on the [PhyDemo (phydemo.app)](/phydemo) website (formerly on ricktu288.github.io). The source code is [available on GitHub](/github), and you are [welcome to contribute](/contributing). If you have questions or suggestions, you can open [issues](/github/issues) or [discussions](/github/discussions) on GitHub, or email us at [ray-optics@phydemo.app](/email) if you do not use GitHub.", + "cite": "Cite this project", + "mainAuthors_one": "Main Author", + "mainAuthors_other": "Main Authors", + "contributors": "Contributors", + "contributorSorting": "GitHub contributors first; others sorted chronologically.", + "contributionCategories": { + "code": "code", + "uiDesign": "UI design", + "gallery": "gallery", + "module": "module", + "translations_one": "{{languages}} translation", + "translations_other": "{{languages}} translations" + } + }, + "languageDropdown": { + "title": "Language: {{language}}", + "translatedFraction": "{{fraction}} translated" + } +} diff --git a/locales/en/modules.json b/locales/en/modules.json new file mode 100644 index 00000000..10d895c7 --- /dev/null +++ b/locales/en/modules.json @@ -0,0 +1,141 @@ +{ + "modulesPage": { + "description": { + "makeNewTools": "The \"Module\" feature allows making new tools by combining, specializing, or reparametrizing objects created by existing tools in this simulator.", + "appearAsTools": "Imported modules will appear as tools in the \"Other\" category. Please select and click the blank space according to the order of the control point sequence (see \"Specification\").", + "embeddedInScene": "Imported modules are embedded in the data of the scene, so will not be automatically updated when the authors of the modules update them." + }, + "import": "Import", + "imported": "Imported", + "specification": { + "title": "Specification", + "controlPointSequence": "Control point sequence", + "parameters": "Parameters" + }, + "customization": { + "title": "Customization", + "description": "Modules can be made or customized directly within the web app using the built-in JSON editor. See [the tutorial](/modules/tutorial). Customization of imported modules will only affect the current scene." + }, + "contribution": { + "title": "Contribution", + "description": "Contributing to the list above is welcome. To contribute your module, see [Contributing modules](/contributing/modules)." + } + }, + "moduleData": { + "FresnelLens": { + "title": "Fresnel Lens", + "description": "A Fresnel lens made from a half circle piece of glass. Modularized version of [this Gallery example](/gallery/fresnel-lens).", + "point1": "The first endpoint of the lens", + "point2": "The second endpoint of the lens", + "Nslice": "The number of slices", + "refIndex": "The refractive index of the lens" + }, + "ContSpectrum": { + "title": "Continuous spectrum light source", + "description": "A light source with a uniform continuous spectrum decretized with a given constant step. Only works when \"Simulate Colors\" is on.", + "point1": "The origin of the rays", + "point2": "Determines the direction of the rays", + "min": "The minimum wavelength", + "step": "The step of the wavelength", + "max": "The maximum wavelength", + "brightness": "The total brightness" + }, + "CircleSource": { + "title": "Circular light source", + "description": "A circle with uniform 180-degree point sources places along its circumference.", + "point1": "The center of the circle", + "r": "The radius of the circle", + "N": "The number of point sources", + "brightness": "The total brightness" + }, + "Chaff": { + "title": "Chaff", + "description": "A chaff of a rectangular shape consisting of random pieces of mirrors. Modularized version of [this Gallery example](/gallery/chaff-countermeasure).", + "point1": "The top-left corner of the chaff", + "point2": "The bottom-right corner of the chaff", + "N": "The number of mirrors in the chaff", + "L": "The length of the mirrors" + }, + "BeamExpander": { + "title": "Beam Expander", + "description": "The combination of two ideal lenses with the sum of their focal lengths equals their separation distance. They expand or reduce the diameter of a beam of collimated light. Modularized version of [this Gallery example](/gallery/beam-expanders).", + "point1": "The center of the first lens", + "point2": "The second point of the second lens", + "point3": "Determines the common focal point of the lenses" + }, + "RayRelay": { + "title": "Ray Relay", + "description": "A series of ideal identical lenses with focal length \\(f\\) and distance \\(d\\) between the lenses. A non-divergent ray trajectory is guaranteed if and only if \\(d\\leq 4f\\). Modularized version of [this Gallery example](/gallery/ray-relaying).", + "point1": "The first endpoint of the first lens", + "point2": "The second endpoint of the first lens (should have the same \\(x\\) as the first point)", + "f": "The focal length of the lenses", + "d": "The distance between the lenses", + "N": "The number of lenses" + }, + "OpticalFiber": { + "title": "Optical Fiber", + "description": "Line-shaped optical fiber with given core and cladding thickness and refractive indices.", + "point1": "The first endpoint of the optical fiber", + "point2": "The second endpoint of the optical fiber (should have the same \\(y\\) as the first point)", + "X": "The thickness of the core", + "Y": "The thickness of the cladding", + "n1": "The refractive index of the core", + "n2": "The refractive index of the cladding" + } + }, + "moduleTutorial": { + "title": "Tutorial for making Ray Optics Modules", + "opening": { + "description": "This tutorial will guide you through the basics of making a custom module, which can be done entirely within the web app, without the need of any external development environment.", + "moduleIntroduction": "The \"Module\" feature of Ray Optics Simulation allows the creation of modular combinations of objects with custom parameters, custom control points, and arrays of objects. This feature extends the capability of this simulator by combining, specializing, or reparametrizing objects created by existing tools to make new tools. For example, the `CircleSource` module (see Tools -> Other -> Import module) combines an array of point sources created by the existing \"Point Source (<360°)\" tool along a circle, to make a \"circular source\" tool which didn't exist in the simulator. The `FresnelLens` module specializes the \"Glass->Custom equation\" tool, so that the equation represents a specific curve of the Fresnel lens parametrized by the number of slices, thus making a specialized \"Fresnel lens\" tool, which also didn't exist before. In addition to making new tools, this feature can also make some optics demonstrations more interactive. For example, by dragging the third control point of the `BeamExpander` module, one can directly see how the position of the common focal point of the two lenses affects the beam width, without needing to adjust the focal lengths of the two lenses individually.", + "compareWithHandle": "Note that not all custom control points require a module. Some simple cases can be achieved by the \"handle\" feature (see the \"Group, rotate, and scale objects\" section in the help popup at the bottom right corner of the simulator). Since making a module is much more complicated than creating a handle, you should first check if your case can be achieved by the \"handle\" feature before considering making a module. See [here](/gallery/black-cat-becomes-white) for a non-trivial example of a custom control point (moving two plastic bags out of water) without using a module." + }, + "jsonEditor": { + "title": "The built-in JSON editor", + "currentlyNoVisual": "This app currently does not have a visual interface for creating modules, so you need to directly edit the JSON of the scene.", + "enableJsonEditor": "You can enable the built-in JSON editor by clicking the \"settings\" dropdown at the top-right corner of the app, and then check \"Show JSON editor\". The code editor should appear at the left-hand side of the app, with the JSON code of the current scene. Make sure you have a large enough screen, as this feature does not work well on mobile devices.", + "updateAccordingly": "As you edit the scene using the usual visual scene editor, the code in the JSON editor will update accordingly, with the changed part highlighted. Conversely, directly editing the code in the JSON editor will update the scene accordingly. If you are not familiar with JSON or any kind of text-based data format, you may wish to play around with it for a while.", + "objsArray": "In particular, when you add an object to the scene, it is added to the `objs` array. And if you modify some of its properties to a non-default value, they appear as key-value pairs in that object.", + "inIframesBelow": "IMPORTANT: In this tutorial page, if you do not see the JSON code editor in the iframes below, please turn it on and reload this page, as you will need to see the code to understand how it works." + }, + "basics": { + "title": "Basics of a module", + "lookAtExample": "Let's look at our first example of a module.", + "lookAtJson": "You should see four lines of texts. By looking at the JSON editor, you will see that the first two are directly in the top-level `objs` array as usual, but the last two are in `modules.ExampleModule.objs` instead.", + "moduleDef": "The `module` is a dictionary where the key is the name of the module (in this case `ExampleModule`), and the value is the definition of that module. In particular, the `modules.ExampleModule.objs` array describes the (template of) objects within that module, which is different from the top-level `objs` which describes the objects in the scene.", + "putToScene": "To put the objects within the module to the scene, we need a \"module object\" in the top-level `objs` array, which is `objs[2]` in this example, whose type is `ModuleObj` and whose `module` property is the name of the module.", + "moduleDefNotEditable": "The module definition in the `modules` dictionary is not editable by the visual scene editor. So when you click any of the last two texts in this example, you are just selecting the module object, and not the objects in the module. Since the coordinates of the texts in the module definition in this example are absolute coordinates, the last two texts are not draggable. We will learn how to make them draggable by using control points later.", + "demodulize": "If you select a module object, there is a \"Demodulize\" button on the object bar. Clicking it will \"expand\" the module object into its constituent, and `objs` will now contain all the four texts. This operation is not reversible (but of course you can click \"undo\").", + "createModule": "The suggested way of creating a module currently is to first create an empty module using the JSON editor, create some objects using the visual scene editor, and then cut and paste the objects from `objs` to `modules.ModuleName.objs` using the JSON editor." + }, + "parameters": { + "title": "Adding parameters", + "lookAtExample": "The objects within the module can be defined by a set of parameters. Let’s look at a simple example", + "paramsArray": "Here `modules.ModuleName.params` is an array of strings `\"name=start:step:end:default\"` defining the name of the variables and the range of the sliders. The sliders appear on the object bar when the module object is selected.", + "equationSyntax": "Within the `modules.ExampleModule.objs` array, any values can be expressed using those parameters. Within a string (such as the `text` property of a `TextLabel`), the equations of the variables are enclosed by a pair of backticks. For number parameters (such as the `fontSize` property of a `TextLabel`), you need to make it a string so that you can use the backtick format in it, so each equation is sandwiched by a pair of backticks and a pair of quotes. The equation are evaluated with math.js ([syntax](/mathjs/syntax)). See there for the available syntax and functions you can use in the equations.", + "valueStorage": "The actual values of the parameters are stored in the `params` property of the module object, which, unlike the module definition, can be directly edited by the scene editor using the slider." + }, + "controlPoints": { + "title": "Adding control points", + "lookAtExample": "To make the module object draggable, we need to parametrize the objects within the module using a set of control points. Let’s look at the example", + "coordinatesOfControlPoints": "Here `modules.ModuleName.numPoints` defines the number of control points. The coordinates of the control points are (`x_1`, `y_1`), (`x_2`, `y_2`), etc, and are used in the same ways as the parameters within `modules.ExampleModule.objs` as described by the previous section. Note that the index starts from 1.", + "valueStorage": "The actual values of the coordinates of the control points are stored in the `points` property of the module object, which, unlike the hard-coded coordinates in Example 1, can be edited by the visual scene editor by dragging the control points, each shown as two concentric gray circles in the scene. If you drag elsewhere in the module object (such as dragging the text labels), all the control points will move together.", + "createAsTool": "Since our module object can now move, it is now quite easy to create multiple instances as in usual tools. The name of the module is shown in the Tools -> Other menu, and you can select that and then click two points in the blank space in sequence for the two control points to create another instance of the module. You can also use the “duplicate” button on the object bar." + }, + "arrayAndConditional": { + "title": "Arrays and conditionals", + "lookAtExample": "More complicated module can be built using arrays and conditionals. Let’s look at the example", + "specialKeys": "Within `modules.ExampleModule.objs`, any objects in an array can have two special keys: `\"for\"` and `\"if\"`. The value of the `\"for\"` key is either a string of the format `\"name=start:step:end\"` defining a loop variable, or an array of several strings of this format describing a multidimensional loop. Such an object in the array is duplicated several times according to the loop variables. The value of the `\"if\"` key is a string representing a math.js expression that evaluates to a boolean, and such an object is included in the array if and only if the boolean is true.", + "preventInfiniteLoop": "To prevent accidental infinite loop, the total number of iteration of each `\"for\"` loop is limited by the `maxLoopLength` property of the module definition, whose default value is 1000. You can set this property to a larger value if needed." + }, + "objsWithEqn": { + "title": "Objects with built-in custom equations", + "description": "For objects that already have custom equation input (such as Mirror -> Custom Equation), the equation property in the JSON is a string representing a LaTeX equation, rather than a math.js expression. To include custom parameters in the equation, you must use the same template syntax as if the LaTeX equation were a regular text. So the part enclosed by the backticks is in math.js expression, while the part outside is in LaTeX. The module parameters can only be accessed in the math.js part, and the independent variables of the custom equation (e.g. \\(x\\)) can only be accessed in the LaTeX part. Here is an example of generating a mirror with equation \\(y=\\cos(2\\pi x+\\phi)\\), where \\(\\phi\\) is a module parameter", + "future": "In the future, there may be a way to unified the equation input." + }, + "objsWithShapeParam": { + "title": "Objects with built-in shape parametrization", + "description": "For objects that already support different ways to define its shape (currently only Glass -> Spherical lens). There are special JSON syntax for such objects that can be used within the module definition, even if they are always defined by shape in the top level `objs` array. Here is an example" + } + } +} \ No newline at end of file diff --git a/locales/en/simulator.json b/locales/en/simulator.json new file mode 100644 index 00000000..db5e5f77 --- /dev/null +++ b/locales/en/simulator.json @@ -0,0 +1,335 @@ +{ + "welcome": { + "title": "Welcome to Ray Optics Simulation", + "instruction": "To add an optical component, select a tool and click the blank space.\nTo load an example, please [go to the Gallery page](/gallery).", + "loading": "Loading scene from URL... Please wait." + }, + "common": { + "saveButton": "Save", + "cancelButton": "Cancel", + "defaultOption": "Default", + "closeButton": "Close" + }, + "file": { + "title": "File", + "undo": { + "title": "Undo" + }, + "redo": { + "title": "Redo" + }, + "reset": { + "title": "Reset" + }, + "save": { + "title": "Save" + }, + "open": { + "title": "Open", + "description": "Open an existing file or background image. The background image will be shown from the coordinate origin. (Or drop the file)" + }, + "export": { + "title": "Export as PNG/SVG" + }, + "copyLink": { + "title": "Copy Shareable Link", + "description": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." + }, + "viewGallery": { + "title": "View Gallery", + "description": "Go to the Gallery webpage to load an example." + } + }, + "settings": { + "title": "Settings", + "more": "More", + "rayDensity": { + "title": "Ray Density", + "description": "Determines the number of rays to be emitted by beams and point sources. This also affects the accuracy of image detection and color rendering." + }, + "layoutAids": { + "title": "Layout Aids", + "showGrid": "Grid", + "snapToGrid": "Snap to Grid", + "lockObjs": "Lock Objects" + }, + "gridSize": { + "title": "Grid Size" + }, + "observerSize": { + "title": "Observer Size" + }, + "lengthScale": { + "title": "Length Scale", + "description": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." + }, + "zoom": { + "title": "Zoom" + }, + "language": { + "title": "Language" + }, + "autoSyncUrl": { + "title": "Auto sync URL", + "description": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." + }, + "showJsonEditor": { + "title": "Show JSON editor", + "description": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." + }, + "showStatusBox": { + "title": "Show status box", + "description": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." + }, + "showHelpPopups": { + "title": "Show help popups", + "description": "Defines whether to show help popups when hovering over buttons. (Reload the page to take effect.)" + }, + "advancedHelp": "For advanced help, see the help icon in the lower-right corner." + }, + "objBar": { + "showAdvanced": { + "title": "More options..." + }, + "applyToAll": { + "title": "Apply to All" + }, + "duplicate": { + "title": "Duplicate" + }, + "delete": { + "title": "Delete" + }, + "unselect": { + "title": "Unselect", + "description": "Unselect this object (Right-click on blank space has the same function.)" + } + }, + "sceneObjs": { + "common": { + "lengthUnitInfo": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale.", + "brightness": "Brightness", + "brightnessInfo": { + "rayDensity": "Only effective if 'Ray Density' is high enough.", + "rayDensitySlider": "To control the numbers of rays emitted, please adjust the global 'Ray Density' slider instead." + }, + "wavelength": "Wavelength", + "emisAngle": "Emission Angle", + "random": "Random", + "lambert": "Lambertian", + "focalLength": "Focal length", + "eqnInfo": { + "constants": "Supported constants", + "operators": "Supported operators", + "functions": "Supported functions" + }, + "imageDetectionWarning": "This tool does not support image detection.", + "nonSimulateColorsWarning": "This tool only works when \"Simulate Color\" is on." + }, + "Beam": { + "imageDetectionWarning": "Image detection may not work with divergent/random beams." + }, + "AngleSource": { + "symmetric": "Symmetric" + }, + "BaseFilter": { + "filter": "Filter", + "bandwidth": "Bandwidth", + "invert": "Invert" + }, + "IdealMirror": { + "cartesianSign": "Cartesian Sign Convention" + }, + "BeamSplitter": { + "transRatio": "Transmission Ratio" + }, + "BaseGlass": { + "refIndex": "Refractive index", + "refIndexInfo": { + "relative": "Relative if inside another glass", + "effective": "If this object is to be simulated with (absolute) refractive index n₁, but is placed inside another glass with refractive index n₀, then you should set the refractive index to n₁/n₀ here. In more complicated cases that several glasses overlap together, the effective reflective index of the overlapping region equals the product of the reflective indices of individual ones." + }, + "cauchyCoeff": "Cauchy coefficient" + }, + "SphericalLens": { + "defBy": { + "radiiOfCurvature": "Radii of Curvature", + "focalDistances": "Focal Distances" + } + }, + "BaseGrinGlass": { + "refIndexFnInfo": { + "constants": "Supported constants", + "operators": "Supported operators", + "functions": "Supported functions", + "lambda": "To simulate chromatic dispersion, use parameter {{lambda}} for the vacuum wavelength in nanometers.", + "diff": "Only supports differentiable functions.", + "origin": "The origin of n(x,y) is in the absolute coordinates and does not move with the object. You may double-click a control-point to inspect its absolute coordinates.", + "accuracy": "For a more accurate simulation, see \"More options...\"" + }, + "refIndexFnOrigin": "Origin of n(x,y)", + "stepSize": "Numerical solver step size", + "stepSizeInfo": "Step size of Euler's method for solving the eikonal ray equation - see 'step' function and documentation inside the 'BaseGrinGlass.js' file, for more information.", + "intersectTol": "Intersection tolerance", + "symbolicBodyMerging": "Symbolic body-merging", + "symbolicBodyMergingInfo": { + "all": "This toggle applies to all GRIN objects in the simulation.", + "impl": "This simulator has currently two implementations of light propagation between different mediums, for GRIN objects - numerical and symbolic (see 'multRefIndex' and 'devRefIndex' functions in 'BaseGrinGlass.js').", + "implNote": "The numerical implementation is faster but doesn't always work properly (depending on the specific case) in scenarios when used with more than one GRIN object, such that at least one of them has a refractive index function which is not defined in the entire plane, while the symbolic implementation is slower but robust to such problems." + } + }, + "CircleGrinGlass": { + "epsInfo": { + "units": "Units - [length]^2.", + "functions": "This numerical tolerance is used in the functions 'isOutsideGlass', 'isInsideGlass' and 'isOnBoundary', inside the 'CircleGrinGlass.js' file." + } + }, + "GrinGlass": { + "epsInfo": { + "units": "Units - [length].", + "functions": "This numerical tolerance is used in the functions 'isOnBoundary' and 'countIntersections', inside the 'GrinGlass.js' file." + } + }, + "Aperature": { + "diameter": "Diameter" + }, + "DiffractionGrating": { + "lineDensity": "Lines/{{lengthUnit}}", + "customBrightness": "Custom Brightness", + "customBrightnessInfo": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored.", + "slitRatio": "Slit width / line spacing", + "mirrored": "Mirrored" + }, + "Ruler": { + "scaleInterval": "Scale interval" + }, + "Detector": { + "info": { + "P": "P: The rate of energy flow (flux) in B/s (see below).", + "Fperp": "F⊥: The rate of perpendicular momentum flow in (B/s)/c.", + "Fpar": "F∥: The rate of parallel momentum flow in (B/s)/c.", + "irradiance": "The irradiance in the exported CSV is in (B/s)/L.", + "length": "L is the arbitrary unit of length used in this simulator.", + "B": "B is an arbitrary unit of radiant flux or luminous flux, corresponding to the unit of the \"Brightness\" option being B/L for non-Lambertian beams and 500B/360° for point sources.", + "s": "The dimensionless factor s is the \"Brightness Scale\" shown in Settings -> Show status box, which equals 1 when \"Ray Density\" is above some threshold and proportional to \"Ray Density\" otherwise.", + "truncation": "If some rays are truncated in the infinite series of internal reflection, the total truncation is shown as error estimates." + }, + "irradMap": "Irradiance Map", + "binSize": "Bin Size", + "exportData": "Export data" + }, + "TextLabel": { + "textHere": "Text Here", + "fontSize": "Font Size", + "font": "Font", + "fontStyle": "Style", + "fontStyles": { + "normal": "Normal", + "bold": "Bold", + "italic": "Italic", + "boldItalic": "Bold Italic", + "oblique": "Oblique", + "boldOblique": "Bold Oblique" + }, + "alignment": "Alignment", + "alignments": { + "left": "Left", + "center": "Centre", + "right": "Right" + }, + "smallCaps": "Small Caps", + "angle": "Angle" + }, + "LineArrow": { + "arrow": "Forward arrow", + "backArrow": "Backward arrow" + }, + "Drawing": { + "finishDrawing": "Finish Drawing" + }, + "ModuleObj": { + "module": "Module", + "demodulize": "Demodulize" + }, + "Handle": { + "handle": "Handle", + "transformation": "Transformation", + "transformations": { + "translation": "Translation", + "xTranslation": "X Translation", + "yTranslation": "Y Translation", + "rotation": "Rotation", + "scaling": "Scaling" + } + }, + "CropBox": { + "title": "Export", + "cropBoxSize": "Crop Box Size", + "format": "Format", + "width": "Width", + "rayCountLimit": "Ray count limit", + "svgWarning": "Export to SVG: Color mixtures and relative refractive indices below 1 are not supported.", + "rayCountWarning": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." + } + }, + "saveModal": { + "title": "Save", + "description": { + "autoSync": "You may use Settings -> Auto sync URL instead of saving to a file.", + "rename": "Click \"Rename\" to change the title without saving to a file.", + "contribute": "You may consider [contributing a new item](/contributing/gallery) to the [Gallery](/gallery)." + }, + "fileName": "Name", + "rename": "Rename" + }, + "moduleModal": { + "title": "Import Modules", + "makeCustomModules": "Make custom modules", + "conflict": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." + }, + "languageModal": { + "title": "Language", + "translatedFraction": "translated", + "helpTranslate": "Help us translate this app" + }, + "generalWarnings": { + "shareLinkTooLong": "The URL is too long that it may not work on some platforms. You may need to use \"Save\" and share the file instead.", + "autoSyncUrlTooLarge": "The scene is too large to sync with URL. Please save it manually.", + "identicalObjects": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior.", + "brightnessInconsistent": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." + }, + "statusBox": { + "rayCount": "Number of ray segments", + "totalTruncation": "Truncated brightness", + "brightnessScale": "Brightness Scale", + "timeElapsed": "Time elapsed", + "forceStopped": "Force stopped.", + "mouseCoordinates": "Mouse coordinates" + }, + "footer": { + "processing": "Processing... Click here to stop.", + "helpPopup": { + "constrainedDragging": { + "title": "Constrained dragging", + "description": "When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center." + }, + "groupRotateScale": { + "title": "Group, rotate, and scale objects", + "description": "Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate the group, Ctrl+Shift+drag to scale the group. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup." + }, + "editCoordinates": { + "title": "Edit coordinates directly", + "description": "Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter." + }, + "keyboardShortcuts": { + "title": "Keyboard shortcuts", + "description": "When an object is selected (by clicking it), press arrow keys to move the object; Ctrl+D to duplicate the object; Delete key to delete the object." + }, + "contactUs": { + "title": "Contact Us", + "description": "The suggested way is to go to [Discussions](/github/discussions) or [Issues](/github/issues) on GitHub. If you do not use GitHub, you can also email us at [ray-optics@phydemo.app](/email).", + "contribute": "Direct contributions are also welcome (see [the contribution guide](/contributing))." + } + } + } +} \ No newline at end of file diff --git a/locales/es.json b/locales/es.json deleted file mode 100644 index 8e9f730b..00000000 --- a/locales/es.json +++ /dev/null @@ -1,914 +0,0 @@ -{ - "appName": { - "message": "Simulador - Simulación de trazado de rayos" - }, - "appShortName": { - "message": "Óptica de rayos" - }, - "appDesc": { - "message": "Una aplicación web gratuita y de código libre para crear y simular escenas 2D de óptica geométrica." - }, - "homepage_desc": { - "message": "Crear y simular escenas 2D de óptica geométrica de manera interactiva.
Totalmente gratuito y basado en web. El código fuente está disponible en GitHub." - }, - "launch_simulator": { - "message": "Iniciar simulador" - }, - "home": { - "message": "Inicio" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/es/" - }, - "gallery": { - "message": "Galería" - }, - "gallery_url": { - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "message": "Bienvenido a la simulación de Óptica de rayos
Para añadir un componente óptico, seleccione una herramienta y presione el espacio en blanco.
Para cargar un ejemplo, por favor, diríjase a la página de la galería." - }, - "loading_msg": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
Loading scene from URL... Please wait." - }, - "toolbar_title": { - "message": "Herramienta: " - }, - "toolname_SingleRay": { - "message": "Rayo único" - }, - "toolname_AngleSource": { - "message": "Fuente puntual" - }, - "toolname_PointSource": { - "message": "Fuente puntual" - }, - "toolname_Beam": { - "message": "Rayo" - }, - "toolname_mirror_": { - "message": "Espejo" - }, - "toolname_Mirror": { - "message": "Espejo" - }, - "toolname_ArcMirror": { - "message": "Espejo" - }, - "toolname_ParabolicMirror": { - "message": "Espejo" - }, - "toolname_CustomMirror": { - "message": "Espejo" - }, - "toolname_IdealMirror": { - "message": "Espejo curvo ideal" - }, - "toolname_glass_": { - "message": "Vidrio" - }, - "toolname_blocker_": { - "message": "Bloqueador" - }, - "toolname_BeamSplitter": { - "message": "Separador de haz" - }, - "toolname_PlaneGlass": { - "message": "Vidrio" - }, - "toolname_CircleGlass": { - "message": "Vidrio" - }, - "toolname_CircleGrinGlass": { - "message": "Círculo con gradiente de índice" - }, - "toolname_Glass": { - "message": "Arcos poligonales/ circulares" - }, - "toolname_GrinGlass": { - "message": "Polígono con gradiente de índice" - }, - "toolname_IdealLens": { - "message": "Lente ideal" - }, - "toolname_SphericalLens": { - "message": "Lente esférica" - }, - "toolname_CustomGlass": { - "message": "Vidrio" - }, - "toolname_Blocker": { - "message": "Bloqueador recto" - }, - "toolname_Aperture": { - "message": "Apertura" - }, - "toolname_CircleBlocker": { - "message": "Bloqueador circular" - }, - "toolname_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "toolname_Ruler": { - "message": "Regla" - }, - "toolname_Protractor": { - "message": "Transportador" - }, - "tool_Detector": { - "message": "Detector" - }, - "toolname_Detector": { - "message": "Detector" - }, - "toolname_TextLabel": { - "message": "Texto" - }, - "toolname_LineArrow": { - "message": "Línea" - }, - "toolname_Drawing": { - "message": "Dibujar" - }, - "toolname_Handle": { - "incomplete": true, - "message": "Handle" - }, - "toolname_CropBox": { - "message": "Exportar" - }, - "toolname_ModuleObj": { - "incomplete": true, - "message": "ModuleBeta" - }, - "tool_more_": { - "message": "Otros" - }, - "toolname_": { - "message": "Mover vista" - }, - "modebar_title": { - "message": "Ver:" - }, - "modename_light": { - "message": "Rayos" - }, - "modename_extended_light": { - "message": "Rayos extendidos" - }, - "modename_images": { - "message": "Todas las imágenes" - }, - "modename_observer": { - "message": "Visto por un observador" - }, - "simulateColors": { - "message": "Simular colores" - }, - "File: ": { - "message": "Archivo" - }, - "Tools: ": { - "message": "Herramientas" - }, - "tool_SingleRay": { - "message": "Rayo único" - }, - "tool_Beam": { - "message": "Haz" - }, - "tool_PointSource": { - "message": "Fuente puntual (360°)" - }, - "tool_AngleSource": { - "message": "Fuente puntual (<360°)" - }, - "tool_PointSource_": { - "message": "Fuente puntual" - }, - "tool_lightSource_": { - "message": "Fuente de luz" - }, - "tool_mirror_": { - "message": "Espejo" - }, - "tool_Mirror": { - "message": "Segmento" - }, - "tool_ArcMirror": { - "message": "Arco circular" - }, - "tool_ParabolicMirror": { - "message": "Parabólico" - }, - "tool_CustomMirror": { - "message": "Ecuación personalizada" - }, - "tool_BeamSplitter": { - "message": "Separador de haz" - }, - "tool_IdealMirror": { - "message": "Curvo ideal" - }, - "tool_glass_": { - "message": "Vidrio" - }, - "tool_blocker_": { - "message": "Bloqueador" - }, - "tool_PlaneGlass": { - "message": "Semi-plano" - }, - "tool_CircleGlass": { - "message": "Círculo" - }, - "tool_CircleGrinGlass": { - "message": "Círculo" - }, - "tool_Glass": { - "message": "Forma libre" - }, - "tool_GrinGlass": { - "message": "Forma libre" - }, - "tool_IdealLens": { - "message": "Lente ideal" - }, - "tool_SphericalLens": { - "message": "Lente esférica" - }, - "tool_CustomGlass": { - "message": "Ecuación personalizada" - }, - "tool_Blocker": { - "message": "Bloqueador recto" - }, - "tool_Aperture": { - "message": "Apertura" - }, - "tool_CircleBlocker": { - "message": "Bloqueador circular" - }, - "tool_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "tool_Ruler": { - "message": "Regla" - }, - "tool_Protractor": { - "message": "Transportador" - }, - "tool_TextLabel": { - "message": "Texto" - }, - "tool_LineArrow": { - "message": "Línea / Flecha" - }, - "tool_Drawing": { - "message": "Dibujar" - }, - "tool_": { - "message": "Mover vista" - }, - "View: ": { - "message": "Vista" - }, - "Settings: ": { - "message": "Ajustes" - }, - "moresettings": { - "message": "Más" - }, - "mode_rays": { - "message": "Rayos" - }, - "mode_extended": { - "message": "Rayos extendidos" - }, - "mode_images": { - "message": "Todas las imágenes" - }, - "mode_observer": { - "message": "Visto por el observador" - }, - "zoom": { - "message": "Zoom" - }, - "help": { - "message": "Ayuda" - }, - "rayDensity": { - "message": "Densidad de rayos" - }, - "raydensity": { - "message": "Densidad de rayos:" - }, - "undo": { - "message": "Deshacer" - }, - "redo": { - "message": "Rehacer" - }, - "reset": { - "message": "Restablecer" - }, - "save": { - "message": "Guardar" - }, - "rename": { - "incomplete": true, - "message": "Rename" - }, - "get_link": { - "message": "Copiar enlace compartible" - }, - "export_svg": { - "message": "Exportar como PNG/SVG" - }, - "view_gallery": { - "message": "Ver galería" - }, - "save_name": { - "message": "Nombre" - }, - "save_cancel": { - "message": "Cancelar" - }, - "save_description": { - "incomplete": true, - "message": "" - }, - "open": { - "message": "Abrir" - }, - "layoutaids": { - "message": "Ayuda con el diseño" - }, - "lockObjs": { - "message": "Bloquear objetos" - }, - "showGrid": { - "message": "Cuadrícula" - }, - "snapToGrid": { - "message": "Ajustar a la cuadrícula" - }, - "snaptogrid": { - "message": "Ajustar a la cuadrícula" - }, - "length_unit_popover": { - "incomplete": true, - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "incomplete": true, - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "incomplete": true, - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "message": "Brillo" - }, - "wavelength": { - "message": "Longitud de onda (nm)" - }, - "dichroic": { - "message": "Dicroico" - }, - "filter": { - "message": "Filtro" - }, - "bandwidth": { - "message": "Ancho de banda (nm)" - }, - "invert": { - "message": "Invertir" - }, - "emisAngle": { - "message": "Angulo de emisión (°)" - }, - "mirrored": { - "incomplete": true, - "message": "Mirrored" - }, - "lineDensity": { - "incomplete": true, - "message": "Lines/mm" - }, - "slitRatio": { - "incomplete": true, - "message": "Slit width / line spacing" - }, - "customBrightness": { - "incomplete": true, - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "incomplete": true, - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "message": "Simétrico" - }, - "eqn_note": { - "incomplete": true, - "message": "" - }, - "symbolic_grin": { - "message": "Unión simbólica de cuerpos" - }, - "grin_refractive_index": { - "incomplete": true, - "message": "" - }, - "symbolic_grin_note_popover": { - "message": "

Esta opción se aplica a todos los objetos GRIN de la simulación.

Actualmente este simulador tiene dos implementaciones de propagación de la luz entre medios, para objetos GRIN - numéricos y simbólicos (vea las funciones 'multRefIndex' y 'devRefIndex' en 'CircleGrinGlass.js').

La implementación numérica es más rápida pero no siempre funciona correctamente (dependiendo del caso en concreto) en escenarios donde se usa más de un objeto GRIN,tal que al menos una de ellas tiene una función de índice de refracción que no está definida en todo el plano, mientras que la implementación simbólica és más lenta pero robusta con estos problemas.

" - }, - "focalLength": { - "message": "Distancia focal" - }, - "cartesianSign": { - "message": "Convenio de signos cartesiano" - }, - "refIndex": { - "message": "Indice de refracción*" - }, - "radii_of_curvature": { - "message": "Radios de curvatura" - }, - "focal_distances": { - "message": "Distancias focales" - }, - "refIndex_origin": { - "message": "Origen de n(x,y)" - }, - "stepSize": { - "message": "Tamaño de paso de la solución numérica" - }, - "intersectTol": { - "message": "Tolerancia de la intersección" - }, - "random": { - "message": "Aleatorio" - }, - "lambert": { - "message": "Lambertiana" - }, - "diameter": { - "message": "Diámetro" - }, - "irradMap": { - "message": "Mapa de irradiación" - }, - "binSize": { - "message": "Tamaño del contenedor" - }, - "scaleInterval": { - "incomplete": true, - "message": "Scale interval" - }, - "exportData": { - "message": "Exportar datos" - }, - "demodulize": { - "incomplete": true, - "message": "Demodulize" - }, - "fontSize": { - "message": "Tamaño de fuente" - }, - "font": { - "message": "Fuente" - }, - "fontStyle": { - "message": "Estilo" - }, - "normal": { - "message": "Normal" - }, - "bold": { - "message": "Negrita" - }, - "italic": { - "message": "Cursiva" - }, - "bolditalic": { - "message": "Negrita cursiva" - }, - "oblique": { - "message": "Oblicua" - }, - "boldoblique": { - "message": "Negrita oblicua" - }, - "alignment": { - "message": "Alineamiento" - }, - "left": { - "message": "Izquierda" - }, - "center": { - "message": "Centro" - }, - "right": { - "message": "Derecha" - }, - "text_here": { - "message": "Texto Aquí" - }, - "smallCaps": { - "message": "Mayúsculas pequeñas" - }, - "angle": { - "message": "Angulo (°)" - }, - "arrow": { - "message": "Flecha adelante" - }, - "backArrow": { - "message": "Flecha atrás" - }, - "stop_drawing": { - "message": "Finalizar dibujo" - }, - "cropBoxSize": { - "message": "Tamaño de crop box" - }, - "format": { - "message": "Formato" - }, - "width": { - "message": "Ancho" - }, - "rayCountLimit": { - "incomplete": true, - "message": "Ray count limit" - }, - "transformation": { - "incomplete": true, - "message": "TransformationBeta" - }, - "default": { - "incomplete": true, - "message": "Default" - }, - "translation": { - "incomplete": true, - "message": "Translation" - }, - "xTranslation": { - "incomplete": true, - "message": "X Translation" - }, - "yTranslation": { - "incomplete": true, - "message": "Y Translation" - }, - "rotation": { - "incomplete": true, - "message": "Rotation" - }, - "scaling": { - "incomplete": true, - "message": "Scaling" - }, - "beam_warning": { - "message": "Detección de imagen puede no funcionar con rayos divergentes/ aleatorios" - }, - "image_detection_warning": { - "incomplete": true, - "message": "This tool does not support image detection." - }, - "non_simulateColors_warning": { - "incomplete": true, - "message": "This tool only works when \"Simulate Color\" is on." - }, - "brightness_note_popover": { - "message": "

Solo es efectivo si la 'Densidad de rayos' es suficientemente alta.

Para controlar el número de rayos emitidos, por favor ajustar el deslizante global 'Densidad de rayos'.

" - }, - "refIndex_note_popover": { - "message": "

*Relativo si esta dentro de otro vidrio

Si este objeto se tiene que simular con un índice de refracción (absoluto) n₁, pero esta situado dentro de otro vidrio con índice de refracción n₀, entonces deberá establecer el índice de refracción en n₁/n₀ aquí. En casos más complicados donde varios vidrios se sobrepongan, el índice de refracción efectivo de la región sobrepuesta es igual al producto de los índices de refracción por separado.

" - }, - "stepSize_note_popover": { - "message": "

Tamaño de paso para el método de Euler para resolver la ecuación de la eikonal de rayos - ver la función 'step' y la documentación dentro del archivo 'grin_ciclelens.js' para más información.

" - }, - "eps_CircleGrinGlass_note_popover": { - "message": "

Unidades - [longitud]^2.

Esta tolerancia numérica se usa en las funciones 'isOutsideGlass', 'isInsideGlass' y 'isOnBoundary', dentro del archivo 'CircleGrinGlass.js'.

" - }, - "eps_GrinGlass_note_popover": { - "message": "

Unidades - [longitud].

Esta tolerancia numérica se usa en las funciones 'isOnBoundary' y 'countIntersections', dentro del archivo 'GrinGlass.js'.

" - }, - "cauchyCoeff": { - "message": "Coeficiente de Cauchy" - }, - "transRatio": { - "message": "Cociente de transmisión" - }, - "applytoall": { - "message": "Aplicar a todos" - }, - "duplicate": { - "message": "Duplicar" - }, - "delete": { - "message": "Borrar" - }, - "unselect": { - "message": "Deseleccionar" - }, - "unselect_popover": { - "message": "Deseleccionar este objecto (click derecho en un espacio en blanco tiene la misma función.)" - }, - "showadvanced": { - "message": "Más opciones..." - }, - "processing": { - "message": "Procesando... Click aquí para detener." - }, - "contribute": { - "message": "Contribuir" - }, - "github": { - "message": "GitHub" - }, - "about": { - "message": "Acerca de" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "message": "Ayúdenos a traducir esta aplicación" - }, - "translated": { - "message": "traducida" - }, - "undo_popover": { - "message": "Deshacer última acción. (Ctrl+Z)" - }, - "redo_popover": { - "message": "Rehacer última acción. (Ctrl+Y)" - }, - "reset_popover": { - "message": "Restablecer todos los cambios." - }, - "save_popover": { - "message": "Guardar la escena actual como un archivo." - }, - "open_popover": { - "message": "Abrir un archivo existente o una imagen de fondo. La imagen de fondo se mostrará desde el origen de coordenadas. (O arrastre el archivo)." - }, - "get_link_popover": { - "incomplete": true, - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "message": "La URL es demasiado larga y posiblemente no funcione en algunas plataformas. Posiblemente deba usar \"Guardar\" y compartir el archivo." - }, - "export_svg_warning": { - "message": "Exportar a SVG. Las mezclas de color y indices de refracción relativos por debajo de 1 no están soportados." - }, - "export_ray_count_warning": { - "incomplete": true, - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "message": "Ir a la Galería para cargar un ejemplo." - }, - "tool_SingleRay_popover": { - "message": "Un único rayo de luz definido mediante dos puntos. (Arrastre o clique para crear. El primer punto es la fuente, emitiendo en dirección al segundo punto.)" - }, - "tool_Beam_popover": { - "message": "Un haz de rayos paralelo o divergente emerge de un segmento de recta, con una densidad controlada por el deslizante 'Densidad de rayos' (Arrastre o clique para crear.)" - }, - "tool_PointSource_popover": { - "message": "Los rayos emergen de un único punto, con un número controlado por el deslizante 'Densidad de rayos'. (Clique para crear)." - }, - "tool_AngleSource_popover": { - "message": "Fuente puntual con un ángulo de emisión dado." - }, - "tool_Mirror_popover": { - "message": "Simular la reflexión de la luz en un espejo. (Arrastre o clique para crear)." - }, - "tool_ArcMirror_popover": { - "message": "Un espejo cuya forma es parte de un círculo, el cual está definido por tres puntos. (Arrastre o clique para crear. Los dos primeros puntos definen el espacio entre los bordes del arco. El último define el tamaño del arco.)" - }, - "tool_ParabolicMirror_popover": { - "message": "Un espejo cuya forma es una parábola, la cual está definida pr tres puntos. (Arrastre o clique para crear.)" - }, - "tool_CustomMirror_popover": { - "message": "Un espejo cuya forma está definida por una ecuación de la forma y = f(x), donde (x,y) está en las coordenadas transformadas donde los dos puntos de control son (-1,0) y (1,0). (Arrastre o clique para crear.)" - }, - "tool_BeamSplitter_popover": { - "message": "Un espejo que transmite un porcentaje de la luz incidente. (Arrastre o clique para crear.)" - }, - "tool_IdealMirror_popover": { - "message": "Un espejo 'curvo' ideal que obedece exactamente la ecuación del espejo (1/p + 1/q = 1/f). La longitud focal puede establecerse directamente. (Arrastre o clique para crear.)" - }, - "tool_PlaneGlass_popover": { - "message": "Simular la refracción y la reflexión de luz sobre una superficie. (Arrastre o clique para crear.)" - }, - "tool_CircleGlass_popover": { - "message": "Vidrio con una forma circular, definida mediante su centro y un punto sobre la superficie. (Arrastre o clique para crear.)" - }, - "tool_CircleGrinGlass_popover": { - "message": "Vidrio con una función de índice refractivo n(x,y) y un borde circular. (Arrastre o clique para crear.)" - }, - "tool_Glass_popover": { - "message": "Vidrio con cualquier forma construida mediante segmentos de línea o arco. (Clique para crear un segmento, arrastre para crear un arco, clique en el punto de inicio cuando haya finalizado el dibujo.)" - }, - "tool_GrinGlass_popover": { - "message": "Vidrio con una función de índice de refracción n(x,y) y un borde poligonal. ATENCIÓN: Sólo se soportan polígonos simples, de otro modo el comportamiento es impredecible. (Clique para crear un segmento, clique en el punto de inicio cuando haya finalizado el dibujo.)" - }, - "tool_IdealLens_popover": { - "message": "Una lente ideal que obedece exactamente la ecuación de las lentes delgadas (1/p + 1/q = 1/f). La longitud focal se puede establecer directamente. (Arrastre o clique para crear.)" - }, - "tool_SphericalLens_popover": { - "message": "Una lente esférica. (Click para crear.)" - }, - "tool_CustomGlass_popover": { - "message": "Vidrio con una forma definida por una desigualdad f(x) < y < g(x), donde (x,y) está en las coordenadas transformadas donde los dos puntos de control son (-1,0) y (1,0). (Arrastre o clique para crear.)" - }, - "tool_Blocker_popover": { - "message": "Un bloqueador de luz recto que absorbe los rayos incidentes. (Arrastre o clique para crear.)" - }, - "tool_Aperture_popover": { - "message": "Un par de bloqueadores de luz que absorben los rayos incidentes. El tamaño del agujero puede ajustarse simétricamente. (Arrastre o clique los dos puntos extremales para crear.)" - }, - "tool_CircleBlocker_popover": { - "message": "Un bloqueador de luz circular que absorbe los rayos incidentes. (Arrastre o clique para crear.)" - }, - "tool_DiffractionGrating_popover": { - "incomplete": true, - "message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)" - }, - "tool_Ruler_popover": { - "message": "Una regla desde un punto cero hasta otro punto. (Arrastre o clique para crear.)" - }, - "tool_Protractor_popover": { - "message": "Un transportador definido desde el centro y otro punto para la dirección cero. La escala está en grados. (Arrastre o clique para crear.)" - }, - "tool_Detector_popover": { - "message": "Una herramienta para medir el flujo de energía (P), el momento perpendicular de flujo (F⊥), y el momento paralelo de flujo (F∥) a través de un segmento de recta. (Arrastre o clique para crear el segmento de recta.) Las unidades son arbitrarias." - }, - "tool_Detector_info_popover": { - "incomplete": true, - "message": "" - }, - "tool_TextLabel_popover": { - "message": "Un cuadro de texto." - }, - "tool_LineArrow_popover": { - "message": "Un segmento de recta o flecha. (Arrastre o clique para crear.)" - }, - "tool_Drawing_popover": { - "message": "Una herramienta para dibujar a mano alzada. (Arrastre para dibujar.)" - }, - "tool__popover": { - "message": "Arrastre para mover la vista. (El botón derecho del ratón tiene la misma función.)" - }, - "mode_rays_popover": { - "message": "Mostrar los rayos. Cuando la 'Densidad de rayos' es elevada, estos parecen continuos." - }, - "mode_extended_popover": { - "message": "Mostrar los rayos y su extensión. El color naranja indica extensiones hacia atrás, y el gris indica hacia delante.
Cuando 'Simular colores' está seleccionado, estos se muestran en los colores de la fuente y se distinguen por un trazo discontinuo." - }, - "mode_images_popover": { - "message": "Mostrar la posición de todas las imágenes. Los puntos amarillos indican imágenes reales, naranjas indican imágenes virtuales, y grises (ninguno en esta figura) indican objetos virtuales. Cabe notar que algunas imágenes no se pueden detectar si 'Densidad de rayos' no es suficientemente elevada.
Cuando 'Simular colores' está seleccionado estos se muestran en los colores de la fuente y se distinguen por el tamaño del punto." - }, - "mode_observer_popover": { - "message": "Simular los rayos y las imágenes vistos desde una posición. El circulo azul es el observador. Cualquier rayo que lo cruce se considera 'observado'. El observador no sabe donde inician los rayos, pero puede pensar que tienen inicio en algún(os) punto(s) si se intersectan ahí. Los rayos se muestran en azul, y los puntos en amarillo (reales) o naranja (virtuales). (Arrastre el punto azul grande para mover al observador.)
Cuando 'Simular colores' está seleccionado, se muestran en los colores de la fuente." - }, - "simulateColors_popover": { - "message": "Simular colores (longitudes de onda), mezclas de colores, filtros de color de bloqueadores y espejos y dispersión cromática de vidrios. Puede ajustar los parámetros de estos objetos cuando los seleccione. Para simular el espectro de colores, sobreponga rayos con diferentes longitudes de onda. Los colores mostrados en pantalla son solo aproximaciones burdas y puede ser muy impreciso cuando 'Densidad de rayos' es demasiado alta o demasiado baja." - }, - "rayDensity_popover": { - "message": "Determinar el numero de rayos emitidos por haces y fuentes puntuales. Esto también afecta a la precisión de la detección de las imágenes y a la renderización del color." - }, - "showGrid_popover": { - "message": "Define la visibilidad de la cuadrícula de fondo." - }, - "grid_popover": { - "message": "Define si ajustar a la cuadrícula." - }, - "lockObjs_popover": { - "message": "Define si los objetos pueden ser movidos o no." - }, - "zoom_popover": { - "message": "Zoom de la vista con porcentaje." - }, - "help_popover": { - "incomplete": true, - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "message": "Mostrar ventanas de ayuda" - }, - "show_help_popups_popover": { - "message": "Definir si mostrar ventanas de ayuda al pasar sobre los botones (Volver a cargar las páginas para que tome efecto.)" - }, - "show_json_editor": { - "incomplete": true, - "message": "Show JSON editorBeta" - }, - "show_json_editor_popover": { - "incomplete": true, - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "message": "Mostrar diálogo de estado" - }, - "show_status_popover": { - "incomplete": true, - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "incomplete": true, - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "incomplete": true, - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "incomplete": true, - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "message": "Tamaño de la cuadrícula" - }, - "observer_size": { - "message": "Tamaño del observador" - }, - "language": { - "message": "Idioma" - }, - "close": { - "message": "Cerrar" - }, - "advanced_help": { - "message": "Para ayuda avanzada, vea el icono de ayuda en la esquina inferior derecha." - }, - "ray_count": { - "message": "Número de segmentos de rayo: " - }, - "total_truncation": { - "message": "Brillo truncado: " - }, - "brightness_scale": { - "incomplete": true, - "message": "Brightness Scale: " - }, - "time_elapsed": { - "message": "Tiempo transcurrido (ms): " - }, - "force_stopped": { - "message": "Fuerza detenida." - }, - "mouse_coordinates": { - "incomplete": true, - "message": "Mouse coordinates: " - }, - "modules_tutorial": { - "incomplete": true, - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "incomplete": true, - "message": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior." - }, - "import_modules": { - "incomplete": true, - "message": "Import Modules..." - }, - "import_modules_title": { - "incomplete": true, - "message": "Import Modules" - }, - "modules_url": { - "incomplete": true, - "message": "../modules/modules.html" - }, - "remove_module": { - "incomplete": true, - "message": "Remove module" - }, - "module_conflict": { - "incomplete": true, - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "incomplete": true, - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/es/main.json b/locales/es/main.json new file mode 100644 index 00000000..b4dd4e74 --- /dev/null +++ b/locales/es/main.json @@ -0,0 +1,204 @@ +{ + "meta": { + "languageName": "Español", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "Simulación de trazado de rayos", + "shortName": "Óptica de rayos", + "description": "Una aplicación web gratuita y de código libre para crear y simular escenas 2D de óptica geométrica." + }, + "pages": { + "simulator": "Simulador", + "home": "Inicio", + "gallery": "Galería", + "about": "Acerca de", + "github": "GitHub" + }, + "homePage": { + "description": "Crear y simular escenas 2D de óptica geométrica de manera interactiva.\nTotalmente gratuito y basado en web. El código fuente está [disponible en GitHub](/github).", + "launchSimulator": "Iniciar simulador" + }, + "tools": { + "title": "Herramientas", + "categories": { + "lightSource": "Fuente de luz", + "mirror": "Espejo", + "glass": "Vidrio", + "blocker": "Bloqueador", + "other": "Otros" + }, + "common": { + "clickInstruction": "Clique para crear.", + "lineInstruction": "Arrastre o clique para crear.", + "circleInstruction": "Arrastre o clique para crear." + }, + "SingleRay": { + "title": "Rayo único", + "description": "Un único rayo de luz definido mediante dos puntos.", + "instruction": "Arrastre o clique para crear. El primer punto es la fuente, emitiendo en dirección al segundo punto." + }, + "Beam": { + "title": "Haz", + "description": "Un haz de rayos paralelo o divergente emerge de un segmento de recta, con una densidad controlada por el deslizante 'Densidad de rayos'" + }, + "PointSource": { + "title": "Fuente puntual", + "description": "Los rayos emergen de un único punto, con un número controlado por el deslizante 'Densidad de rayos'." + }, + "AngleSource": { + "instruction": "Arrastre o clique para crear. El primer punto es la fuente, emitiendo en dirección al segundo punto.", + "description": "Fuente puntual con un ángulo de emisión dado." + }, + "Mirror": { + "title": "Segmento", + "description": "Simular la reflexión de la luz en un espejo." + }, + "otherMirror": { + "title": "Curvado", + "description": "Un espejo cuya forma es curva. Puede ser circular, parabólico o definido mediante una ecuación de la forma y = f(x)." + }, + "ArcMirror": { + "title": "Arco circular", + "description": "Un espejo cuya forma es parte de un círculo, el cual está definido por tres puntos.", + "instruction": "Arrastre o clique para crear. Los dos primeros puntos definen el espacio entre los bordes del arco. El último define el tamaño del arco." + }, + "ParabolicMirror": { + "title": "Parabólico", + "description": "Un espejo cuya forma es una parábola, la cual está definida pr tres puntos.", + "instruction": "Arrastre o clique para crear." + }, + "CustomMirror": { + "title": "Ecuación personalizada", + "description": "Un espejo cuya forma está definida por una ecuación de la forma y = f(x), donde (x,y) está en las coordenadas transformadas donde los dos puntos de control son (-1,0) y (1,0)." + }, + "IdealMirror": { + "title": "Curvo ideal", + "description": "Un espejo 'curvo' ideal que obedece exactamente la ecuación del espejo (1/p + 1/q = 1/f). La longitud focal puede establecerse directamente." + }, + "BeamSplitter": { + "title": "Separador de haz", + "description": "Un espejo que transmite un porcentaje de la luz incidente." + }, + "PlaneGlass": { + "title": "Semi-plano", + "description": "Simular la refracción y la reflexión de luz sobre una superficie.", + "instruction": "Arrastre o clique para crear." + }, + "otherGlass": { + "title": "Otras formas", + "description": "Vidrio con otras formas construidas a partir de segmentos de lineas y arcos, o formas definidas mediante una desigualdad de la forma f(x) < y < g(x)." + }, + "CircleGlass": { + "title": "Círculo", + "description": "Vidrio con una forma circular, definida mediante su centro y un punto sobre la superficie." + }, + "Glass": { + "title": "Forma libre", + "description": "Vidrio con cualquier forma construida mediante segmentos de línea o arco.", + "instruction": "Clique para crear un segmento, arrastre para crear un arco, clique en el punto de inicio cuando haya finalizado el dibujo." + }, + "CustomGlass": { + "title": "Ecuación personalizada", + "description": "Vidrio con una forma definida por una desigualdad f(x) < y < g(x), donde (x,y) está en las coordenadas transformadas donde los dos puntos de control son (-1,0) y (1,0)." + }, + "IdealLens": { + "title": "Lente ideal", + "description": "Una lente ideal que obedece exactamente la ecuación de las lentes delgadas (1/p + 1/q = 1/f). La longitud focal se puede establecer directamente." + }, + "SphericalLens": { + "title": "Lente esférica", + "description": "Una lente esférica." + }, + "CircleGrinGlass": { + "title": "Círculo", + "description": "Vidrio con una función de índice refractivo n(x,y) y un borde circular." + }, + "GrinGlass": { + "title": "Forma libre", + "description": "Vidrio con una función de índice de refracción n(x,y) y un borde poligonal.", + "instruction": "Clique para crear un segmento, clique en el punto de inicio cuando haya finalizado el dibujo.", + "warning": "ATENCIÓN: Sólo se soportan polígonos simples, de otro modo el comportamiento es impredecible." + }, + "otherGrinGlass": { + "title": "Polígono con gradiente de índice" + }, + "Blocker": { + "title": "Bloqueador recto", + "description": "Un bloqueador de luz recto que absorbe los rayos incidentes." + }, + "CircleBlocker": { + "title": "Bloqueador circular", + "description": "Un bloqueador de luz circular que absorbe los rayos incidentes." + }, + "Aperture": { + "title": "Apertura", + "description": "Un par de bloqueadores de luz que absorben los rayos incidentes. El tamaño del agujero puede ajustarse simétricamente.", + "instruction": "Arrastre o clique los dos puntos extremales para crear." + }, + "Ruler": { + "title": "Regla", + "description": "Una regla desde un punto cero hasta otro punto." + }, + "Protractor": { + "title": "Transportador", + "description": "Un transportador definido desde el centro y otro punto para la dirección cero. La escala está en grados." + }, + "Detector": { + "title": "Detector", + "description": "Una herramienta para medir el flujo de energía (P), el momento perpendicular de flujo (F⊥), y el momento paralelo de flujo (F∥) a través de un segmento de recta. Las unidades son arbitrarias." + }, + "TextLabel": { + "title": "Texto", + "description": "Un cuadro de texto." + }, + "LineArrow": { + "title": "Línea / Flecha", + "description": "Un segmento de recta o flecha." + }, + "Drawing": { + "title": "Dibujar", + "description": "Una herramienta para dibujar a mano alzada.", + "instruction": "Arrastre para dibujar." + }, + "moveView": { + "title": "Mover vista", + "description": "Arrastre para mover la vista. (El botón derecho del ratón tiene la misma función.)" + } + }, + "view": { + "title": "Vista", + "rays": { + "title": "Rayos", + "description": "Mostrar los rayos. Cuando la 'Densidad de rayos' es elevada, estos parecen continuos." + }, + "extended": { + "title": "Rayos extendidos", + "description": "Mostrar los rayos y su extensión. El color naranja indica extensiones hacia atrás, y el gris indica hacia delante.", + "simulateColorsNote": "Cuando 'Simular colores' está seleccionado, estos se muestran en los colores de la fuente y se distinguen por un trazo discontinuo." + }, + "images": { + "title": "Todas las imágenes", + "description": "Mostrar la posición de todas las imágenes. Los puntos amarillos indican imágenes reales, naranjas indican imágenes virtuales, y grises (ninguno en esta figura) indican objetos virtuales. Cabe notar que algunas imágenes no se pueden detectar si 'Densidad de rayos' no es suficientemente elevada.", + "simulateColorsNote": "Cuando 'Simular colores' está seleccionado estos se muestran en los colores de la fuente y se distinguen por el tamaño del punto." + }, + "observer": { + "title": "Visto por el observador", + "description": "Simular los rayos y las imágenes vistos desde una posición. El circulo azul es el observador. Cualquier rayo que lo cruce se considera 'observado'. El observador no sabe donde inician los rayos, pero puede pensar que tienen inicio en algún(os) punto(s) si se intersectan ahí. Los rayos se muestran en azul, y los puntos en amarillo (reales) o naranja (virtuales).", + "simulateColorsNote": "Cuando 'Simular colores' está seleccionado, se muestran en los colores de la fuente.", + "instruction": "Arrastre el punto azul grande para mover al observador." + } + }, + "simulateColors": { + "title": "Simular colores", + "description": "Simular colores (longitudes de onda), mezclas de colores, filtros de color de bloqueadores y espejos y dispersión cromática de vidrios.", + "instruction": "Puede ajustar los parámetros de estos objetos cuando los seleccione. Para simular el espectro de colores, sobreponga rayos con diferentes longitudes de onda.", + "warning": "Los colores mostrados en pantalla son solo aproximaciones burdas y puede ser muy impreciso cuando 'Densidad de rayos' es demasiado alta o demasiado baja." + }, + "languageDropdown": { + "title": "Idioma: {{language}}", + "translatedFraction": "{{fraction}} traducida" + } +} \ No newline at end of file diff --git a/locales/es/simulator.json b/locales/es/simulator.json new file mode 100644 index 00000000..1b6cde37 --- /dev/null +++ b/locales/es/simulator.json @@ -0,0 +1,226 @@ +{ + "welcome": { + "title": "Bienvenido a la simulación de Óptica de rayos", + "instruction": "Para añadir un componente óptico, seleccione una herramienta y presione el espacio en blanco.\nPara cargar un ejemplo, por favor, [diríjase a la página de la galería](/gallery)." + }, + "common": { + "saveButton": "Guardar", + "cancelButton": "Cancelar", + "closeButton": "Cerrar" + }, + "file": { + "title": "Archivo", + "undo": { + "title": "Deshacer" + }, + "redo": { + "title": "Rehacer" + }, + "reset": { + "title": "Restablecer" + }, + "save": { + "title": "Guardar" + }, + "open": { + "title": "Abrir", + "description": "Abrir un archivo existente o una imagen de fondo. La imagen de fondo se mostrará desde el origen de coordenadas. (O arrastre el archivo)." + }, + "export": { + "title": "Exportar como PNG/SVG" + }, + "copyLink": { + "title": "Copiar enlace compartible" + }, + "viewGallery": { + "title": "Ver galería", + "description": "Ir a la Galería para cargar un ejemplo." + } + }, + "settings": { + "title": "Ajustes", + "more": "Más", + "rayDensity": { + "title": "Densidad de rayos", + "description": "Determinar el numero de rayos emitidos por haces y fuentes puntuales. Esto también afecta a la precisión de la detección de las imágenes y a la renderización del color." + }, + "layoutAids": { + "title": "Ayuda con el diseño", + "showGrid": "Cuadrícula", + "snapToGrid": "Ajustar a la cuadrícula", + "lockObjs": "Bloquear objetos" + }, + "gridSize": { + "title": "Tamaño de la cuadrícula" + }, + "observerSize": { + "title": "Tamaño del observador" + }, + "zoom": { + "title": "Zoom" + }, + "language": { + "title": "Idioma" + }, + "showStatusBox": { + "title": "Mostrar diálogo de estado" + }, + "showHelpPopups": { + "title": "Mostrar ventanas de ayuda", + "description": "Definir si mostrar ventanas de ayuda al pasar sobre los botones (Volver a cargar las páginas para que tome efecto.)" + }, + "advancedHelp": "Para ayuda avanzada, vea el icono de ayuda en la esquina inferior derecha." + }, + "objBar": { + "showAdvanced": { + "title": "Más opciones..." + }, + "applyToAll": { + "title": "Aplicar a todos" + }, + "duplicate": { + "title": "Duplicar" + }, + "delete": { + "title": "Borrar" + }, + "unselect": { + "title": "Deseleccionar", + "description": "Deseleccionar este objecto (click derecho en un espacio en blanco tiene la misma función.)" + } + }, + "sceneObjs": { + "common": { + "brightness": "Brillo", + "brightnessInfo": { + "rayDensity": "Solo es efectivo si la 'Densidad de rayos' es suficientemente alta.", + "rayDensitySlider": "Para controlar el número de rayos emitidos, por favor ajustar el deslizante global 'Densidad de rayos'." + }, + "wavelength": "Longitud de onda", + "emisAngle": "Angulo de emisión", + "random": "Aleatorio", + "lambert": "Lambertiana", + "focalLength": "Distancia focal" + }, + "Beam": { + "imageDetectionWarning": "Detección de imagen puede no funcionar con rayos divergentes/ aleatorios" + }, + "AngleSource": { + "symmetric": "Simétrico" + }, + "BaseFilter": { + "filter": "Filtro", + "bandwidth": "Ancho de banda", + "invert": "Invertir" + }, + "IdealMirror": { + "cartesianSign": "Convenio de signos cartesiano" + }, + "BeamSplitter": { + "transRatio": "Cociente de transmisión" + }, + "BaseGlass": { + "refIndex": "Indice de refracción", + "refIndexInfo": { + "relative": "Relativo si esta dentro de otro vidrio", + "effective": "Si este objeto se tiene que simular con un índice de refracción (absoluto) n₁, pero esta situado dentro de otro vidrio con índice de refracción n₀, entonces deberá establecer el índice de refracción en n₁/n₀ aquí. En casos más complicados donde varios vidrios se sobrepongan, el índice de refracción efectivo de la región sobrepuesta es igual al producto de los índices de refracción por separado." + }, + "cauchyCoeff": "Coeficiente de Cauchy" + }, + "SphericalLens": { + "defBy": { + "radiiOfCurvature": "Radios de curvatura", + "focalDistances": "Distancias focales" + } + }, + "BaseGrinGlass": { + "refIndexFnOrigin": "Origen de n(x,y)", + "stepSize": "Tamaño de paso de la solución numérica", + "stepSizeInfo": "Tamaño de paso para el método de Euler para resolver la ecuación de la eikonal de rayos - ver la función 'step' y la documentación dentro del archivo 'BaseGrinGlass.js' para más información.", + "intersectTol": "Tolerancia de la intersección", + "symbolicBodyMerging": "Unión simbólica de cuerpos", + "symbolicBodyMergingInfo": { + "all": "Esta opción se aplica a todos los objetos GRIN de la simulación.", + "impl": "Actualmente este simulador tiene dos implementaciones de propagación de la luz entre medios, para objetos GRIN - numéricos y simbólicos (vea las funciones 'multRefIndex' y 'devRefIndex' en 'BaseGrinGlass.js').", + "implNote": "La implementación numérica es más rápida pero no siempre funciona correctamente (dependiendo del caso en concreto) en escenarios donde se usa más de un objeto GRIN,tal que al menos una de ellas tiene una función de índice de refracción que no está definida en todo el plano, mientras que la implementación simbólica és más lenta pero robusta con estos problemas." + } + }, + "CircleGrinGlass": { + "epsInfo": { + "units": "Unidades - [longitud]^2.", + "functions": "Esta tolerancia numérica se usa en las funciones 'isOutsideGlass', 'isInsideGlass' y 'isOnBoundary', dentro del archivo 'CircleGrinGlass.js'." + } + }, + "GrinGlass": { + "epsInfo": { + "units": "Unidades - [longitud].", + "functions": "Esta tolerancia numérica se usa en las funciones 'isOnBoundary' y 'countIntersections', dentro del archivo 'GrinGlass.js'." + } + }, + "Aperature": { + "diameter": "Diámetro" + }, + "Detector": { + "irradMap": "Mapa de irradiación", + "binSize": "Tamaño del contenedor", + "exportData": "Exportar datos" + }, + "TextLabel": { + "textHere": "Texto Aquí", + "fontSize": "Tamaño de fuente", + "font": "Fuente", + "fontStyle": "Estilo", + "fontStyles": { + "normal": "Normal", + "bold": "Negrita", + "italic": "Cursiva", + "boldItalic": "Negrita cursiva", + "oblique": "Oblicua", + "boldOblique": "Negrita oblicua" + }, + "alignment": "Alineamiento", + "alignments": { + "left": "Izquierda", + "center": "Centro", + "right": "Derecha" + }, + "smallCaps": "Mayúsculas pequeñas", + "angle": "Angulo" + }, + "LineArrow": { + "arrow": "Flecha adelante", + "backArrow": "Flecha atrás" + }, + "Drawing": { + "finishDrawing": "Finalizar dibujo" + }, + "CropBox": { + "title": "Exportar", + "cropBoxSize": "Tamaño de crop box", + "format": "Formato", + "width": "Ancho", + "svgWarning": "Exportar a SVG. Las mezclas de color y indices de refracción relativos por debajo de 1 no están soportados." + } + }, + "saveModal": { + "title": "Guardar", + "fileName": "Nombre" + }, + "languageModal": { + "title": "Idioma", + "translatedFraction": "traducida", + "helpTranslate": "Ayúdenos a traducir esta aplicación" + }, + "generalWarnings": { + "shareLinkTooLong": "La URL es demasiado larga y posiblemente no funcione en algunas plataformas. Posiblemente deba usar \"Guardar\" y compartir el archivo." + }, + "statusBox": { + "rayCount": "Número de segmentos de rayo", + "totalTruncation": "Brillo truncado", + "timeElapsed": "Tiempo transcurrido", + "forceStopped": "Fuerza detenida." + }, + "footer": { + "processing": "Procesando... Click aquí para detener." + } +} \ No newline at end of file diff --git a/locales/fr.json b/locales/fr.json deleted file mode 100644 index 7549ca91..00000000 --- a/locales/fr.json +++ /dev/null @@ -1,1044 +0,0 @@ -{ - "appName": { - "message": "Simulation de rayon optique" - }, - "appShortName": { - "message": "Rayon optique" - }, - "appDesc": { - "incomplete": true, - "message": "A free, open-source web app for creating and simulating 2D geometric optical scenes." - }, - "homepage_desc": { - "incomplete": true, - "message": "Create & simulate 2D geometric optical scenes interactively.
Totally free and web-based. Source code is available on GitHub." - }, - "launch_simulator": { - "incomplete": true, - "message": "Launch Simulator" - }, - "home": { - "incomplete": true, - "message": "Home" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/fr/" - }, - "gallery": { - "incomplete": true, - "message": "Gallery" - }, - "gallery_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
To add an optical component, select a tool and click the blank space.
To load an example, please go to the Gallery page." - }, - "loading_msg": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
Loading scene from URL... Please wait." - }, - "toolbar_title": { - "message": "Outils: " - }, - "toolname_SingleRay": { - "message": "Rayon" - }, - "toolname_AngleSource": { - "message": "Source de lumière" - }, - "toolname_PointSource": { - "message": "Source de lumière" - }, - "toolname_Beam": { - "message": "Faisceau" - }, - "toolname_mirror_": { - "message": "Miroir" - }, - "toolname_Mirror": { - "message": "Miroir" - }, - "toolname_ArcMirror": { - "message": "Miroir" - }, - "toolname_ParabolicMirror": { - "message": "Miroir" - }, - "toolname_CustomMirror": { - "incomplete": true, - "message": "Mirror" - }, - "toolname_IdealMirror": { - "message": "Miroir parfaitement courbé" - }, - "toolname_glass_": { - "message": "Verre" - }, - "toolname_blocker_": { - "incomplete": true, - "message": "Blocker" - }, - "toolname_BeamSplitter": { - "incomplete": true, - "message": "Beam Splitter" - }, - "toolname_PlaneGlass": { - "message": "Verre" - }, - "toolname_CircleGlass": { - "message": "Verre" - }, - "toolname_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_Glass": { - "message": "Verre" - }, - "toolname_GrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_IdealLens": { - "message": "Lentille idéale" - }, - "toolname_SphericalLens": { - "incomplete": true, - "message": "Spherical lens" - }, - "toolname_CustomGlass": { - "incomplete": true, - "message": "Glass" - }, - "toolname_Blocker": { - "incomplete": true, - "message": "Line Blocker" - }, - "toolname_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "toolname_CircleBlocker": { - "incomplete": true, - "message": "Circle Blocker" - }, - "toolname_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "toolname_Ruler": { - "message": "Règle" - }, - "toolname_Protractor": { - "message": "Rapporteur" - }, - "tool_Detector": { - "incomplete": true, - "message": "Detector" - }, - "toolname_Detector": { - "incomplete": true, - "message": "Detector" - }, - "toolname_TextLabel": { - "message": "Texte" - }, - "toolname_LineArrow": { - "incomplete": true, - "message": "Line" - }, - "toolname_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "toolname_Handle": { - "incomplete": true, - "message": "Handle" - }, - "toolname_CropBox": { - "incomplete": true, - "message": "Export" - }, - "toolname_ModuleObj": { - "incomplete": true, - "message": "ModuleBeta" - }, - "tool_more_": { - "message": "Autre" - }, - "toolname_": { - "message": "Bouger la vue" - }, - "modebar_title": { - "message": "Vue:" - }, - "modename_light": { - "message": "Rayons" - }, - "modename_extended_light": { - "message": "Rayons étendus" - }, - "modename_images": { - "message": "Toutes les images" - }, - "modename_observer": { - "message": "Vu par un observateur" - }, - "simulateColors": { - "incomplete": true, - "message": "Simulate Colors" - }, - "File: ": { - "message": "Fichier" - }, - "Tools: ": { - "message": "Outils" - }, - "tool_SingleRay": { - "message": "Rayon" - }, - "tool_Beam": { - "message": "Faisceau" - }, - "tool_PointSource": { - "message": "Source de lumière (360°)" - }, - "tool_AngleSource": { - "message": "Source de lumière (<360°)" - }, - "tool_PointSource_": { - "message": "Source de lumière" - }, - "tool_lightSource_": { - "message": "Source de lumière" - }, - "tool_mirror_": { - "message": "Miroirs" - }, - "tool_Mirror": { - "message": "Segment" - }, - "tool_ArcMirror": { - "message": "Arc circulaire" - }, - "tool_ParabolicMirror": { - "incomplete": true, - "message": "Parabolic" - }, - "tool_CustomMirror": { - "incomplete": true, - "message": "Custom Equation" - }, - "tool_BeamSplitter": { - "incomplete": true, - "message": "Beam Splitter" - }, - "tool_IdealMirror": { - "message": "Courbure idéale" - }, - "tool_glass_": { - "message": "Verres" - }, - "tool_blocker_": { - "message": "Diaphragme" - }, - "tool_PlaneGlass": { - "message": "Demi-plan" - }, - "tool_CircleGlass": { - "message": "Cercle" - }, - "tool_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index circle" - }, - "tool_Glass": { - "incomplete": true, - "message": "Polygon / Circular Arcs" - }, - "tool_GrinGlass": { - "incomplete": true, - "message": "Gradient-index polygon" - }, - "tool_IdealLens": { - "message": "Lentille idéale" - }, - "tool_SphericalLens": { - "incomplete": true, - "message": "Spherical Lens" - }, - "tool_CustomGlass": { - "incomplete": true, - "message": "Custom Equation" - }, - "tool_Blocker": { - "incomplete": true, - "message": "Line Blocker" - }, - "tool_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "tool_CircleBlocker": { - "incomplete": true, - "message": "Circle Blocker" - }, - "tool_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "tool_Ruler": { - "message": "Règle" - }, - "tool_Protractor": { - "message": "Rapporteur" - }, - "tool_TextLabel": { - "message": "Texte" - }, - "tool_LineArrow": { - "incomplete": true, - "message": "Line / Arrow" - }, - "tool_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "tool_": { - "message": "Bouger la vue" - }, - "View: ": { - "message": "Vue" - }, - "Settings: ": { - "message": "Paramètres" - }, - "moresettings": { - "incomplete": true, - "message": "More" - }, - "mode_rays": { - "message": "Rayons" - }, - "mode_extended": { - "message": "Rayons étendus" - }, - "mode_images": { - "message": "Toutes les images" - }, - "mode_observer": { - "message": "Vu par un observateur" - }, - "zoom": { - "message": "Zoom" - }, - "help": { - "message": "Aide" - }, - "rayDensity": { - "message": "Densité de rayon" - }, - "raydensity": { - "message": "Densité de rayon:" - }, - "undo": { - "message": "Annuler" - }, - "redo": { - "message": "Rétablir" - }, - "reset": { - "message": "Recommencer" - }, - "save": { - "message": "Sauvegarder" - }, - "rename": { - "incomplete": true, - "message": "Rename" - }, - "get_link": { - "incomplete": true, - "message": "Copy Shareable Link" - }, - "export_svg": { - "incomplete": true, - "message": "Export as PNG/SVG" - }, - "view_gallery": { - "incomplete": true, - "message": "View Gallery" - }, - "save_name": { - "message": "Nom" - }, - "save_cancel": { - "message": "Annuler" - }, - "save_description": { - "incomplete": true, - "message": "" - }, - "open": { - "message": "Ouvrir" - }, - "layoutaids": { - "incomplete": true, - "message": "Layout Aids" - }, - "lockObjs": { - "message": "Verrouiller les objets" - }, - "showGrid": { - "message": "Grille" - }, - "snapToGrid": { - "message": "Attacher à la grille" - }, - "snaptogrid": { - "message": "Attacher à la grille" - }, - "length_unit_popover": { - "incomplete": true, - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "incomplete": true, - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "incomplete": true, - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "message": "Luminosité" - }, - "wavelength": { - "message": "Longueur d'onde (nm)" - }, - "dichroic": { - "message": "Dichroïque" - }, - "filter": { - "message": "Filtre" - }, - "bandwidth": { - "message": "Bande Passante (nm)" - }, - "invert": { - "message": "Renverser" - }, - "emisAngle": { - "incomplete": true, - "message": "Emission Angle (°)" - }, - "mirrored": { - "incomplete": true, - "message": "Mirrored" - }, - "lineDensity": { - "incomplete": true, - "message": "Lines/mm" - }, - "slitRatio": { - "incomplete": true, - "message": "Slit width / line spacing" - }, - "customBrightness": { - "incomplete": true, - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "incomplete": true, - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "incomplete": true, - "message": "Symmetric" - }, - "eqn_note": { - "incomplete": true, - "message": "" - }, - "symbolic_grin": { - "incomplete": true, - "message": "Symbolic body-merging" - }, - "grin_refractive_index": { - "incomplete": true, - "message": "" - }, - "symbolic_grin_note_popover": { - "incomplete": true, - "message": "

This toggle applies to all GRIN objects in the simulation.

This simulator has currently two implementations of light propagation between different mediums, for GRIN objects - numerical and symbolic (see 'multRefIndex' and 'devRefIndex' functions in 'CircleGrinGlass.js').

The numerical implementation is faster but doesn't always work properly (depending on the specific case) in scenarios when used with more than one GRIN object, such that at least one of them has a refractive index function which is not defined in the entire plane, while the symbolic implementation is slower but robust to such problems.

" - }, - "focalLength": { - "message": "Distance focale" - }, - "cartesianSign": { - "incomplete": true, - "message": "Cartesian Sign Convention" - }, - "refIndex": { - "message": "Indice de réfraction*" - }, - "radii_of_curvature": { - "incomplete": true, - "message": "Radii of Curvature" - }, - "focal_distances": { - "incomplete": true, - "message": "Focal Distances" - }, - "refIndex_origin": { - "incomplete": true, - "message": "Origin of n(x,y)" - }, - "stepSize": { - "incomplete": true, - "message": "Numerical solver step size" - }, - "intersectTol": { - "incomplete": true, - "message": "Intersection tolerance" - }, - "random": { - "incomplete": true, - "message": "Random" - }, - "lambert": { - "incomplete": true, - "message": "Lambertian" - }, - "diameter": { - "incomplete": true, - "message": "Diameter" - }, - "irradMap": { - "incomplete": true, - "message": "Irradiance Map" - }, - "binSize": { - "incomplete": true, - "message": "Bin Size" - }, - "scaleInterval": { - "incomplete": true, - "message": "Scale interval" - }, - "exportData": { - "incomplete": true, - "message": "Export data" - }, - "demodulize": { - "incomplete": true, - "message": "Demodulize" - }, - "fontSize": { - "incomplete": true, - "message": "Font Size" - }, - "font": { - "incomplete": true, - "message": "Font" - }, - "fontStyle": { - "incomplete": true, - "message": "Style" - }, - "normal": { - "incomplete": true, - "message": "Normal" - }, - "bold": { - "incomplete": true, - "message": "Bold" - }, - "italic": { - "incomplete": true, - "message": "Italic" - }, - "bolditalic": { - "incomplete": true, - "message": "Bold Italic" - }, - "oblique": { - "incomplete": true, - "message": "Oblique" - }, - "boldoblique": { - "incomplete": true, - "message": "Bold Oblique" - }, - "alignment": { - "incomplete": true, - "message": "Alignment" - }, - "left": { - "incomplete": true, - "message": "Left" - }, - "center": { - "incomplete": true, - "message": "Centre" - }, - "right": { - "incomplete": true, - "message": "Right" - }, - "text_here": { - "incomplete": true, - "message": "Text Here" - }, - "smallCaps": { - "incomplete": true, - "message": "Small Caps" - }, - "angle": { - "incomplete": true, - "message": "Angle (°)" - }, - "arrow": { - "incomplete": true, - "message": "Forward arrow" - }, - "backArrow": { - "incomplete": true, - "message": "Backward arrow" - }, - "stop_drawing": { - "incomplete": true, - "message": "Finish Drawing" - }, - "cropBoxSize": { - "incomplete": true, - "message": "Crop Box Size" - }, - "format": { - "incomplete": true, - "message": "Format" - }, - "width": { - "incomplete": true, - "message": "Width" - }, - "rayCountLimit": { - "incomplete": true, - "message": "Ray count limit" - }, - "transformation": { - "incomplete": true, - "message": "TransformationBeta" - }, - "default": { - "incomplete": true, - "message": "Default" - }, - "translation": { - "incomplete": true, - "message": "Translation" - }, - "xTranslation": { - "incomplete": true, - "message": "X Translation" - }, - "yTranslation": { - "incomplete": true, - "message": "Y Translation" - }, - "rotation": { - "incomplete": true, - "message": "Rotation" - }, - "scaling": { - "incomplete": true, - "message": "Scaling" - }, - "beam_warning": { - "incomplete": true, - "message": "Image detection may not work with divergent/random beams." - }, - "image_detection_warning": { - "incomplete": true, - "message": "This tool does not support image detection." - }, - "non_simulateColors_warning": { - "incomplete": true, - "message": "This tool only works when \"Simulate Color\" is on." - }, - "brightness_note_popover": { - "incomplete": true, - "message": "

Only effective if 'Ray Density' is high enough.

To control the numbers of rays emitted, please adjust the global 'Ray Density' slider instead.

" - }, - "refIndex_note_popover": { - "incomplete": true, - "message": "

*Relative if inside another glass

If this object is to be simulated with (absolute) refractive index n₁, but is placed inside another glass with refractive index n₀, then you should set the refractive index to n₁/n₀ here. In more complicated cases that several glasses overlap together, the effective reflective index of the overlapping region equals the product of the reflective indices of individual ones.

" - }, - "stepSize_note_popover": { - "incomplete": true, - "message": "

Step size of Euler's method for solving the eikonal ray equation - see 'step' function and documentation inside the 'CircleGrinGlass.js' file, for more information.

" - }, - "eps_CircleGrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length]^2.

This numerical tolerance is used in the functions 'isOutsideGlass', 'isInsideGlass' and 'isOnBoundary', inside the 'CircleGrinGlass.js' file.

" - }, - "eps_GrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length].

This numerical tolerance is used in the functions 'isOnBoundary' and 'countIntersections', inside the 'GrinGlass.js' file.

" - }, - "cauchyCoeff": { - "incomplete": true, - "message": "Cauchy coefficient" - }, - "transRatio": { - "incomplete": true, - "message": "Transmission Ratio" - }, - "applytoall": { - "message": "Appliquer à tous" - }, - "duplicate": { - "message": "Dupliquer" - }, - "delete": { - "message": "Supprimer" - }, - "unselect": { - "incomplete": true, - "message": "Unselect" - }, - "unselect_popover": { - "incomplete": true, - "message": "Unselect this object (Right-click on blank space has the same function.)" - }, - "showadvanced": { - "incomplete": true, - "message": "More options..." - }, - "processing": { - "message": "En cours de traitement... Cliquez ici pour arrêter" - }, - "contribute": { - "incomplete": true, - "message": "Contribute" - }, - "github": { - "incomplete": true, - "message": "GitHub" - }, - "about": { - "incomplete": true, - "message": "About" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "incomplete": true, - "message": "Help us translate this app" - }, - "translated": { - "incomplete": true, - "message": "translated" - }, - "undo_popover": { - "message": "Annuler la dernière action. (Ctrl+Z)" - }, - "redo_popover": { - "message": "Rétablir la dernière action. (Ctrl+Y)" - }, - "reset_popover": { - "message": "Ecraser tous les changements." - }, - "save_popover": { - "message": "Sauvegarder le fichier actuel." - }, - "open_popover": { - "incomplete": true, - "message": "Open an existing file or background image. The background image will be shown from the coordinate origin. (Or drop the file)" - }, - "get_link_popover": { - "incomplete": true, - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "incomplete": true, - "message": "The URL is too long that it may not work on some platforms. You may need to use \"Save\" and share the file instead." - }, - "export_svg_warning": { - "incomplete": true, - "message": "Export to SVG: Color mixtures and relative refractive indices below 1 are not supported." - }, - "export_ray_count_warning": { - "incomplete": true, - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "incomplete": true, - "message": "Go to the Gallery webpage to load an example." - }, - "tool_SingleRay_popover": { - "message": "Un rayon de lumière unique définit par deux points. (Glisser ou cliquer pour le créer. Le premier point est la source, tirant vers le deuxième point.)" - }, - "tool_Beam_popover": { - "incomplete": true, - "message": "A parallel or divergent beam of rays emerges from a line segment, with density controlled by the 'Ray density' slider. (Drag or click to create.)" - }, - "tool_PointSource_popover": { - "message": "Rayons émergeant d'un point unique, avec un nombre de rayons controlé par le curseur 'Densité de rayons'. (Cliquer pour le créer.)" - }, - "tool_AngleSource_popover": { - "incomplete": true, - "message": "Point source with a given emission angle." - }, - "tool_Mirror_popover": { - "message": "Simule la reflexion de la lumière sur un miroir. (Glisser ou cliquer pour le créer.)" - }, - "tool_ArcMirror_popover": { - "message": "Un miroir dont la forme est un arc circulaire, qui est définit par trois points. (Glisser ou cliquer pour le créer. Les deux premiers points définissent l'espace entre les bords de l'arc, le dernier point définit la taille de l'arc.)" - }, - "tool_ParabolicMirror_popover": { - "incomplete": true, - "message": "A mirror whose shape is a parabola, which is defined by three points. (Drag or click to create.)" - }, - "tool_CustomMirror_popover": { - "incomplete": true, - "message": "A mirror whose shape is defined by a custom equation y = f(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0). (Drag or click to create.)" - }, - "tool_BeamSplitter_popover": { - "incomplete": true, - "message": "A mirror that transmits a percentage of incoming light. (Drag or click to create.)" - }, - "tool_IdealMirror_popover": { - "message": "Un miroir 'courbé' qui obéit exactement à l'équation (1/p + 1/q = 1/f). La distance focale peut être défini directement. (Glisser ou cliquer pour le créer.)" - }, - "tool_PlaneGlass_popover": { - "message": "Simule la réfraction et la reflexion de la lumière sur une surface. (Glisser ou cliquer pour le créer.)" - }, - "tool_CircleGlass_popover": { - "message": "Verre avec une forme circulaire, définie par son centre et un point sur sa surface. (Glisser ou cliquer pour le créer.)" - }, - "tool_CircleGrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a circular boundary. (Drag or click to create.)" - }, - "tool_Glass_popover": { - "message": "Verre avec une forme quelconque construite avec des segments et des arcs circulaires. (Cliquer pour crée un segment, glisser pour crée un arc, cliquer sur le point de depart pour finir de dessiner.)" - }, - "tool_GrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a polygonal boundary. WARNING: Only simple polygons are supported, otherwise the behavior is unpredictable. (Click to create a segment, click on the starting point when finish drawing.)" - }, - "tool_IdealLens_popover": { - "message": "Une lentille obéissant exactement à l'équation de lentille (1/p' + 1/p = 1/f'). La distance focale peut être défini directement. (Glisser ou cliquer pour le créer.)" - }, - "tool_SphericalLens_popover": { - "incomplete": true, - "message": "A spherical lens. (Click to create.)" - }, - "tool_CustomGlass_popover": { - "incomplete": true, - "message": "Glass with the shape defined by a custom inequality f(x) < y < g(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0). (Drag or click to create.)" - }, - "tool_Blocker_popover": { - "message": "Un segment absorbant les rayons incidents. (Glisser ou cliquer pour le créer.)" - }, - "tool_Aperture_popover": { - "incomplete": true, - "message": "A pair of light blockers which absorbs the incident rays. The size of the hole can be adjusted symmetrically. (Drag or click the two endpoints to create.)" - }, - "tool_CircleBlocker_popover": { - "incomplete": true, - "message": "A circle light blocker which absorbs the incident rays. (Drag or click to create.)" - }, - "tool_DiffractionGrating_popover": { - "incomplete": true, - "message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)" - }, - "tool_Ruler_popover": { - "message": "Une règle de zéro à un autre point. (Glisser ou cliquer pour le créer.)" - }, - "tool_Protractor_popover": { - "message": "Un rapporteur défini par le centre et un autre point pour la direction zero. L'echelle est en degrès. (Glisser ou cliquer pour le créer.)" - }, - "tool_Detector_popover": { - "incomplete": true, - "message": "A tool for measuring the rate of energy flow (P), the rate of perpendicular momentum flow (F⊥), and the rate of parallel momentum flow (F∥) through a line segment. (Drag or click to create the line segment.) The units are arbitrary." - }, - "tool_Detector_info_popover": { - "incomplete": true, - "message": "" - }, - "tool_TextLabel_popover": { - "message": "Une légende, pour un objet quelconque." - }, - "tool_LineArrow_popover": { - "incomplete": true, - "message": "A line segment or arrow. (Drag or click to create.)" - }, - "tool_Drawing_popover": { - "incomplete": true, - "message": "A freehand drawing tool. (Drag to draw.)" - }, - "tool__popover": { - "message": "Glisser pour bouger la vue. (Le clic droit à la même fonction.)" - }, - "mode_rays_popover": { - "message": "Montre les rayons. Quand la 'Densité de rayons' est élevée, elles paraissent continues." - }, - "mode_extended_popover": { - "incomplete": true, - "message": "Show both the rays and its extension. Orange indicates backward extensions, and gray indicates forward ones.
When 'Simulate Colors' is on, they are shown in source colors and distinguished by dashing instead." - }, - "mode_images_popover": { - "incomplete": true, - "message": "Show the position of all images. Yellow points indicate real images, orange indicates virtual images, and gray (none in this picture) indicates virtual objects. Note that some images cannot be detected if 'Ray density' is not high enough.
When 'Simulate Colors' is on, they are shown in source colors and distinguished by dot sizes instead." - }, - "mode_observer_popover": { - "incomplete": true, - "message": "Simulate the rays and images seen from some position. The blue circle is the observer. Any rays crossing it are considered to be 'observed'. The observer does not know where the rays actually begin, but may think they begin at some point(s) if they intersect there. The rays are shown in blue, and the points in yellow (real) or orange (virtual). (Drag the big blue dot to move the observer.)
When 'Simulate Colors' is on, they are shown in source colors instead." - }, - "simulateColors_popover": { - "incomplete": true, - "message": "Simulate colors (wavelengths) of light sources, mixture of colors, color filtering of blockers and mirrors, and chromatic dispersion of glasses. You can set those parameters for those objects when selected. To simulate color spectra, overlap rays with different wavelengths. The colors shown on the screen are only rough approximations, and can be very inaccurate when 'Ray density' is too high or too low." - }, - "rayDensity_popover": { - "incomplete": true, - "message": "Determines the number of rays to be emitted by beams and point sources. This also affects the accuracy of image detection and color rendering." - }, - "showGrid_popover": { - "message": "Défini la visibilité de l'arrière-plan de la grille." - }, - "grid_popover": { - "message": "Défini si l'on s'accorche à la grille." - }, - "lockObjs_popover": { - "message": "Défini si l'objet peut être bougé ou non." - }, - "zoom_popover": { - "message": "Zoom sur la vue avec un pourcentage." - }, - "help_popover": { - "incomplete": true, - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "incomplete": true, - "message": "Show help popups" - }, - "show_help_popups_popover": { - "incomplete": true, - "message": "Defines whether to show help popups when hovering over buttons. (Reload the page to take effect.)" - }, - "show_json_editor": { - "incomplete": true, - "message": "Show JSON editorBeta" - }, - "show_json_editor_popover": { - "incomplete": true, - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "incomplete": true, - "message": "Show status box" - }, - "show_status_popover": { - "incomplete": true, - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "incomplete": true, - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "incomplete": true, - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "incomplete": true, - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "incomplete": true, - "message": "Grid Size" - }, - "observer_size": { - "incomplete": true, - "message": "Observer Size" - }, - "language": { - "incomplete": true, - "message": "Language" - }, - "close": { - "incomplete": true, - "message": "Close" - }, - "advanced_help": { - "incomplete": true, - "message": "For advanced help, see the help icon in the lower-right corner." - }, - "ray_count": { - "incomplete": true, - "message": "Number of ray segments: " - }, - "total_truncation": { - "incomplete": true, - "message": "Truncated brightness: " - }, - "brightness_scale": { - "incomplete": true, - "message": "Brightness Scale: " - }, - "time_elapsed": { - "incomplete": true, - "message": "Time elapsed (ms): " - }, - "force_stopped": { - "incomplete": true, - "message": "Force stopped." - }, - "mouse_coordinates": { - "incomplete": true, - "message": "Mouse coordinates: " - }, - "modules_tutorial": { - "incomplete": true, - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "incomplete": true, - "message": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior." - }, - "import_modules": { - "incomplete": true, - "message": "Import Modules..." - }, - "import_modules_title": { - "incomplete": true, - "message": "Import Modules" - }, - "modules_url": { - "incomplete": true, - "message": "../modules/modules.html" - }, - "remove_module": { - "incomplete": true, - "message": "Remove module" - }, - "module_conflict": { - "incomplete": true, - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "incomplete": true, - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/fr/main.json b/locales/fr/main.json new file mode 100644 index 00000000..65d05c87 --- /dev/null +++ b/locales/fr/main.json @@ -0,0 +1,126 @@ +{ + "meta": { + "languageName": "Français", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "Simulation de rayon optique", + "shortName": "Rayon optique" + }, + "homePage": { + "description": "Une application web open-source pour simuler la reflexion et refraction de la lumière.\nEcrit en HTML, CSS et JavaScript. ([GitHub](/github))", + "launchSimulator": "Lancer l'application" + }, + "tools": { + "title": "Outils", + "categories": { + "lightSource": "Source de lumière", + "mirror": "Miroirs", + "glass": "Verres", + "blocker": "Diaphragme", + "other": "Autre" + }, + "common": { + "clickInstruction": "Cliquer pour le créer.", + "lineInstruction": "Glisser ou cliquer pour le créer.", + "circleInstruction": "Glisser ou cliquer pour le créer." + }, + "SingleRay": { + "title": "Rayon", + "description": "Un rayon de lumière unique définit par deux points.", + "instruction": "Glisser ou cliquer pour le créer. Le premier point est la source, tirant vers le deuxième point." + }, + "Beam": { + "title": "Faisceau", + "description": "Un faisceau de rayons parallèle émergeant d'un segment, avec une densité controlée par le curseur 'Densité de rayons'. (Also supports divergent beams.)" + }, + "PointSource": { + "title": "Source de lumière", + "description": "Rayons émergeant d'un point unique, avec un nombre de rayons controlé par le curseur 'Densité de rayons'." + }, + "AngleSource": { + "instruction": "Glisser ou cliquer pour le créer. Le premier point est la source, tirant vers le deuxième point." + }, + "Mirror": { + "title": "Segment", + "description": "Simule la reflexion de la lumière sur un miroir." + }, + "otherMirror": { + "title": "Arc circulaire", + "description": "Un miroir dont la forme est un arc circulaire, qui est définit par trois points." + }, + "ArcMirror": { + "title": "Arc circulaire", + "description": "Un miroir dont la forme est un arc circulaire, qui est définit par trois points.", + "instruction": "Glisser ou cliquer pour le créer. Les deux premiers points définissent l'espace entre les bords de l'arc, le dernier point définit la taille de l'arc." + }, + "IdealMirror": { + "title": "Courbure idéale", + "description": "Un miroir 'courbé' qui obéit exactement à l'équation (1/p + 1/q = 1/f). La distance focale peut être défini directement." + }, + "PlaneGlass": { + "title": "Demi-plan", + "description": "Simule la réfraction et la reflexion de la lumière sur une surface.", + "instruction": "Glisser ou cliquer pour le créer." + }, + "otherGlass": { + "title": "Autre", + "description": "Verre avec une forme quelconque construite avec des segments et des arcs circulaires." + }, + "CircleGlass": { + "title": "Cercle", + "description": "Verre avec une forme circulaire, définie par son centre et un point sur sa surface." + }, + "Glass": { + "description": "Verre avec une forme quelconque construite avec des segments et des arcs circulaires.", + "instruction": "Cliquer pour crée un segment, glisser pour crée un arc, cliquer sur le point de depart pour finir de dessiner." + }, + "IdealLens": { + "title": "Lentille idéale", + "description": "Une lentille obéissant exactement à l'équation de lentille (1/p' + 1/p = 1/f'). La distance focale peut être défini directement." + }, + "Blocker": { + "description": "Un segment absorbant les rayons incidents." + }, + "Ruler": { + "title": "Règle", + "description": "Une règle de zéro à un autre point." + }, + "Protractor": { + "title": "Rapporteur", + "description": "Un rapporteur défini par le centre et un autre point pour la direction zero. L'echelle est en degrès." + }, + "TextLabel": { + "title": "Texte", + "description": "Une légende, pour un objet quelconque." + }, + "moveView": { + "title": "Bouger la vue", + "description": "Glisser pour bouger la vue. (Le clic droit à la même fonction.)" + } + }, + "view": { + "title": "Vue", + "rays": { + "title": "Rayons", + "description": "Montre les rayons. Quand la 'Densité de rayons' est élevée, elles paraissent continues." + }, + "extended": { + "title": "Rayons étendus", + "description": "Montre les rayons et leur extensions. Le orange indique les extensions de derrière, le gris les extensions de devant." + }, + "images": { + "title": "Toutes les images", + "description": "Montre la position de toutes les images. Les points jaunes indiquent les images réelles, l'orange indique les images virtuelles et le gris (absent sur l'image) indique les objets virtuels. Notons que certaines images ne peuvent pas être detectées si la 'Densité de rayon' n'est pas suffisament grande." + }, + "observer": { + "title": "Vu par un observateur", + "description": "Simule les rayons et images vus depuis une certaine position. Le cercle bleu est l'observateur. N'importe quel rayon traversant ce cercle est consideré comme 'observé'. L'observateur ne sait pas exactement où le rayon commence réellement, mais pensera qu'il commence à un certain point s'ils se croisent ici. Les rayons sont montrés en bleu, et les points en orange." + } + }, + "languageDropdown": { + "title": "Langue: {{language}}" + } +} \ No newline at end of file diff --git a/locales/fr/simulator.json b/locales/fr/simulator.json new file mode 100644 index 00000000..a3f8d059 --- /dev/null +++ b/locales/fr/simulator.json @@ -0,0 +1,77 @@ +{ + "common": { + "saveButton": "Sauvegarder", + "cancelButton": "Annuler" + }, + "file": { + "title": "Fichier", + "undo": { + "title": "Annuler" + }, + "redo": { + "title": "Rétablir" + }, + "reset": { + "title": "Recommencer" + }, + "save": { + "title": "Sauvegarder" + }, + "open": { + "title": "Ouvrir" + } + }, + "settings": { + "title": "Paramètres", + "rayDensity": { + "title": "Densité de rayon" + }, + "layoutAids": { + "showGrid": "Grille", + "snapToGrid": "Attacher à la grille", + "lockObjs": "Verrouiller les objets" + }, + "zoom": { + "title": "Zoom" + }, + "language": { + "title": "Langue" + } + }, + "objBar": { + "applyToAll": { + "title": "Appliquer à tous" + }, + "duplicate": { + "title": "Dupliquer" + }, + "delete": { + "title": "Supprimer" + } + }, + "sceneObjs": { + "common": { + "brightness": "Luminosité", + "wavelength": "Longueur d'onde", + "focalLength": "Distance focale" + }, + "BaseFilter": { + "filter": "Filtre", + "bandwidth": "Bande Passante", + "invert": "Renverser" + }, + "BaseGlass": { + "refIndex": "Indice de réfraction" + } + }, + "saveModal": { + "title": "Sauvegarder", + "fileName": "Nom" + }, + "languageModal": { + "title": "Langue" + }, + "footer": { + "processing": "En cours de traitement... Cliquez ici pour arrêter" + } +} \ No newline at end of file diff --git a/locales/ja.json b/locales/ja.json deleted file mode 100644 index b2a6ff14..00000000 --- a/locales/ja.json +++ /dev/null @@ -1,987 +0,0 @@ -{ - "appName": { - "message": "光線光学系シミュレーション" - }, - "appShortName": { - "message": "光線光学" - }, - "appDesc": { - "message": "2Dの幾何学的な光学場面を作成し、シミュレーションするための無料のオープンソースのウェブアプリケーションです。" - }, - "homepage_desc": { - "message": "2次元の幾何学的な光学シーンを双方向的にシミュレートすることができます。
完全無料、ウェブベース。ソースコードは GitHubで利用可能です。." - }, - "launch_simulator": { - "message": "シミュレーターを起動" - }, - "home": { - "message": "ホーム" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/jp/" - }, - "gallery": { - "message": "ギャラリー" - }, - "gallery_url": { - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "message": "光学シミュレーションの世界へようこそ
光学部品を追加するには、ツールを選択し、空白部分をクリックします。
例を読み込むには ギャラリーページに移動してください。." - }, - "loading_msg": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
Loading scene from URL... Please wait." - }, - "toolbar_title": { - "message": "ツール: " - }, - "toolname_SingleRay": { - "message": "単一光線" - }, - "toolname_AngleSource": { - "message": "点源" - }, - "toolname_PointSource": { - "message": "点源" - }, - "toolname_Beam": { - "message": "光束" - }, - "toolname_mirror_": { - "message": "鏡" - }, - "toolname_Mirror": { - "message": "鏡" - }, - "toolname_ArcMirror": { - "message": "鏡" - }, - "toolname_ParabolicMirror": { - "message": "鏡" - }, - "toolname_CustomMirror": { - "message": "鏡" - }, - "toolname_IdealMirror": { - "message": "理想的なカーブミラー" - }, - "toolname_glass_": { - "message": "ガラス" - }, - "toolname_blocker_": { - "message": "遮断物" - }, - "toolname_BeamSplitter": { - "message": "ビームスプリッター" - }, - "toolname_PlaneGlass": { - "message": "ガラス" - }, - "toolname_CircleGlass": { - "message": "ガラス" - }, - "toolname_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_Glass": { - "message": "ガラス" - }, - "toolname_GrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_IdealLens": { - "message": "理想的なレンズ" - }, - "toolname_SphericalLens": { - "message": "球面レンズ" - }, - "toolname_CustomGlass": { - "message": "ガラス" - }, - "toolname_Blocker": { - "message": "ラインブロッカー" - }, - "toolname_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "toolname_CircleBlocker": { - "message": "円形ブロッカー" - }, - "toolname_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "toolname_Ruler": { - "message": "定規" - }, - "toolname_Protractor": { - "message": "分度器" - }, - "tool_Detector": { - "message": "検出器" - }, - "toolname_Detector": { - "message": "検出器" - }, - "toolname_TextLabel": { - "message": "テキスト" - }, - "toolname_LineArrow": { - "incomplete": true, - "message": "Line" - }, - "toolname_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "toolname_Handle": { - "incomplete": true, - "message": "Handle" - }, - "toolname_CropBox": { - "incomplete": true, - "message": "Export" - }, - "toolname_ModuleObj": { - "incomplete": true, - "message": "ModuleBeta" - }, - "tool_more_": { - "message": "その他" - }, - "toolname_": { - "message": "ビュー移動" - }, - "modebar_title": { - "message": "表示:" - }, - "modename_light": { - "message": "光線表示" - }, - "modename_extended_light": { - "message": "拡張光線" - }, - "modename_images": { - "message": "すべての画像" - }, - "modename_observer": { - "message": "観察者から見た画像" - }, - "simulateColors": { - "message": "色のシミュレーション" - }, - "File: ": { - "message": "ファイル" - }, - "Tools: ": { - "message": "ツール" - }, - "tool_SingleRay": { - "message": "光線" - }, - "tool_Beam": { - "message": "光束" - }, - "tool_PointSource": { - "message": "点光源 (360°)" - }, - "tool_AngleSource": { - "message": "点光源 (<360°)" - }, - "tool_PointSource_": { - "message": "点光源" - }, - "tool_lightSource_": { - "message": "光源" - }, - "tool_mirror_": { - "message": "鏡" - }, - "tool_Mirror": { - "message": "分割鏡" - }, - "tool_ArcMirror": { - "message": "円弧鏡" - }, - "tool_ParabolicMirror": { - "message": "放物線鏡" - }, - "tool_CustomMirror": { - "message": "カスタム式" - }, - "tool_BeamSplitter": { - "message": "ビームスプリッター" - }, - "tool_IdealMirror": { - "message": "理想的なカーブ" - }, - "tool_glass_": { - "message": "ガラス" - }, - "tool_blocker_": { - "message": "ブロッカ" - }, - "tool_PlaneGlass": { - "message": "半平面" - }, - "tool_CircleGlass": { - "message": "円" - }, - "tool_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index circle" - }, - "tool_Glass": { - "incomplete": true, - "message": "Polygon / Circular Arcs" - }, - "tool_GrinGlass": { - "incomplete": true, - "message": "Gradient-index polygon" - }, - "tool_IdealLens": { - "message": "理想的なレンズ" - }, - "tool_SphericalLens": { - "message": "球面レンズ" - }, - "tool_CustomGlass": { - "message": "カスタム式" - }, - "tool_Blocker": { - "message": "ラインブロッカー" - }, - "tool_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "tool_CircleBlocker": { - "message": "サークルブロッカー" - }, - "tool_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "tool_Ruler": { - "message": "定規" - }, - "tool_Protractor": { - "message": "分度器" - }, - "tool_TextLabel": { - "message": "テキスト" - }, - "tool_LineArrow": { - "incomplete": true, - "message": "Line / Arrow" - }, - "tool_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "tool_": { - "message": "ビューを移動する" - }, - "View: ": { - "message": "ビュー" - }, - "Settings: ": { - "message": "設定" - }, - "moresettings": { - "incomplete": true, - "message": "More" - }, - "mode_rays": { - "message": "光線" - }, - "mode_extended": { - "message": "拡張光線" - }, - "mode_images": { - "message": "すべての画像" - }, - "mode_observer": { - "message": "観察者が見た" - }, - "zoom": { - "message": "ズーム" - }, - "help": { - "message": "ヘルプ" - }, - "rayDensity": { - "message": "光線密度" - }, - "raydensity": { - "message": "光線密度:" - }, - "undo": { - "message": "元に戻す" - }, - "redo": { - "message": "やり直し" - }, - "reset": { - "message": "リセット" - }, - "save": { - "message": "保存" - }, - "rename": { - "incomplete": true, - "message": "Rename" - }, - "get_link": { - "incomplete": true, - "message": "Copy Shareable Link" - }, - "export_svg": { - "incomplete": true, - "message": "Export as PNG/SVG" - }, - "view_gallery": { - "message": "ギャラリーを見る" - }, - "save_name": { - "message": "名前" - }, - "save_cancel": { - "message": "キャンセル" - }, - "save_description": { - "incomplete": true, - "message": "" - }, - "open": { - "message": "開く" - }, - "layoutaids": { - "incomplete": true, - "message": "Layout Aids" - }, - "lockObjs": { - "message": "オブジェクトを固定" - }, - "showGrid": { - "message": "グリッド" - }, - "snapToGrid": { - "message": "グリッドにスナップ" - }, - "snaptogrid": { - "message": "グリッドにスナップ" - }, - "length_unit_popover": { - "incomplete": true, - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "incomplete": true, - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "incomplete": true, - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "message": "明るさ" - }, - "wavelength": { - "message": "波長 (nm)" - }, - "dichroic": { - "message": "ダイクロイック" - }, - "filter": { - "message": "フィルタ" - }, - "bandwidth": { - "message": "帯域幅 (nm)" - }, - "invert": { - "message": "反転" - }, - "emisAngle": { - "message": "放射角度 (°)" - }, - "mirrored": { - "incomplete": true, - "message": "Mirrored" - }, - "lineDensity": { - "incomplete": true, - "message": "Lines/mm" - }, - "slitRatio": { - "incomplete": true, - "message": "Slit width / line spacing" - }, - "customBrightness": { - "incomplete": true, - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "incomplete": true, - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "message": "対称" - }, - "eqn_note": { - "incomplete": true, - "message": "" - }, - "symbolic_grin": { - "incomplete": true, - "message": "Symbolic body-merging" - }, - "grin_refractive_index": { - "incomplete": true, - "message": "" - }, - "symbolic_grin_note_popover": { - "incomplete": true, - "message": "

This toggle applies to all GRIN objects in the simulation.

This simulator has currently two implementations of light propagation between different mediums, for GRIN objects - numerical and symbolic (see 'multRefIndex' and 'devRefIndex' functions in 'CircleGrinGlass.js').

The numerical implementation is faster but doesn't always work properly (depending on the specific case) in scenarios when used with more than one GRIN object, such that at least one of them has a refractive index function which is not defined in the entire plane, while the symbolic implementation is slower but robust to such problems.

" - }, - "focalLength": { - "message": "焦点距離" - }, - "cartesianSign": { - "incomplete": true, - "message": "Cartesian Sign Convention" - }, - "refIndex": { - "message": "屈折率*" - }, - "radii_of_curvature": { - "incomplete": true, - "message": "Radii of Curvature" - }, - "focal_distances": { - "incomplete": true, - "message": "Focal Distances" - }, - "refIndex_origin": { - "incomplete": true, - "message": "Origin of n(x,y)" - }, - "stepSize": { - "incomplete": true, - "message": "Numerical solver step size" - }, - "intersectTol": { - "incomplete": true, - "message": "Intersection tolerance" - }, - "random": { - "message": "ランダム" - }, - "lambert": { - "message": "ランバーシアン" - }, - "diameter": { - "incomplete": true, - "message": "Diameter" - }, - "irradMap": { - "incomplete": true, - "message": "Irradiance Map" - }, - "binSize": { - "incomplete": true, - "message": "Bin Size" - }, - "scaleInterval": { - "incomplete": true, - "message": "Scale interval" - }, - "exportData": { - "incomplete": true, - "message": "Export data" - }, - "demodulize": { - "incomplete": true, - "message": "Demodulize" - }, - "fontSize": { - "message": "フォントサイズ" - }, - "font": { - "message": "フォント" - }, - "fontStyle": { - "message": "スタイル" - }, - "normal": { - "incomplete": true, - "message": "Normal" - }, - "bold": { - "incomplete": true, - "message": "Bold" - }, - "italic": { - "incomplete": true, - "message": "Italic" - }, - "bolditalic": { - "incomplete": true, - "message": "Bold Italic" - }, - "oblique": { - "incomplete": true, - "message": "Oblique" - }, - "boldoblique": { - "incomplete": true, - "message": "Bold Oblique" - }, - "alignment": { - "message": "文字揃え" - }, - "left": { - "incomplete": true, - "message": "Left" - }, - "center": { - "incomplete": true, - "message": "Centre" - }, - "right": { - "incomplete": true, - "message": "Right" - }, - "text_here": { - "incomplete": true, - "message": "Text Here" - }, - "smallCaps": { - "message": "スモールキャピタル" - }, - "angle": { - "message": "角度 (°)" - }, - "arrow": { - "incomplete": true, - "message": "Forward arrow" - }, - "backArrow": { - "incomplete": true, - "message": "Backward arrow" - }, - "stop_drawing": { - "incomplete": true, - "message": "Finish Drawing" - }, - "cropBoxSize": { - "incomplete": true, - "message": "Crop Box Size" - }, - "format": { - "incomplete": true, - "message": "Format" - }, - "width": { - "incomplete": true, - "message": "Width" - }, - "rayCountLimit": { - "incomplete": true, - "message": "Ray count limit" - }, - "transformation": { - "incomplete": true, - "message": "TransformationBeta" - }, - "default": { - "incomplete": true, - "message": "Default" - }, - "translation": { - "incomplete": true, - "message": "Translation" - }, - "xTranslation": { - "incomplete": true, - "message": "X Translation" - }, - "yTranslation": { - "incomplete": true, - "message": "Y Translation" - }, - "rotation": { - "incomplete": true, - "message": "Rotation" - }, - "scaling": { - "incomplete": true, - "message": "Scaling" - }, - "beam_warning": { - "incomplete": true, - "message": "Image detection may not work with divergent/random beams." - }, - "image_detection_warning": { - "incomplete": true, - "message": "This tool does not support image detection." - }, - "non_simulateColors_warning": { - "incomplete": true, - "message": "This tool only works when \"Simulate Color\" is on." - }, - "brightness_note_popover": { - "incomplete": true, - "message": "

Only effective if 'Ray Density' is high enough.

To control the numbers of rays emitted, please adjust the global 'Ray Density' slider instead.

" - }, - "refIndex_note_popover": { - "message": "

*relative if inside another glass

もし(絶対)屈折率n₁でシミュレートされる物体があったとしても、別の屈折率n₀のガラスの中に置かれる場合、ここで屈折率をn₁/n₀に設定する必要があります。複数のガラスが重なり合うような複雑なケースでは、重なり合う領域の実効反射率は、個々のものの反射率の積に等しくなります。

" - }, - "stepSize_note_popover": { - "incomplete": true, - "message": "

Step size of Euler's method for solving the eikonal ray equation - see 'step' function and documentation inside the 'CircleGrinGlass.js' file, for more information.

" - }, - "eps_CircleGrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length]^2.

This numerical tolerance is used in the functions 'isOutsideGlass', 'isInsideGlass' and 'isOnBoundary', inside the 'CircleGrinGlass.js' file.

" - }, - "eps_GrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length].

This numerical tolerance is used in the functions 'isOnBoundary' and 'countIntersections', inside the 'GrinGlass.js' file.

" - }, - "cauchyCoeff": { - "incomplete": true, - "message": "Cauchy coefficient" - }, - "transRatio": { - "message": "透過率" - }, - "applytoall": { - "message": "すべてに適用" - }, - "duplicate": { - "message": "複製" - }, - "delete": { - "message": "消去" - }, - "unselect": { - "incomplete": true, - "message": "Unselect" - }, - "unselect_popover": { - "incomplete": true, - "message": "Unselect this object (Right-click on blank space has the same function.)" - }, - "showadvanced": { - "incomplete": true, - "message": "More options..." - }, - "processing": { - "message": "処理中...停止するにはここをクリックしてください." - }, - "contribute": { - "message": "貢献する" - }, - "github": { - "message": "GitHub" - }, - "about": { - "message": "このソフトウェアについて" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "message": "このアプリの翻訳にご協力ください" - }, - "translated": { - "message": "翻訳済み" - }, - "undo_popover": { - "message": "最後の操作を元に戻します。 (Ctrl+Z)" - }, - "redo_popover": { - "message": "最後の操作をやり直します。 (Ctrl+Y)" - }, - "reset_popover": { - "message": "すべての変更をリセットします。" - }, - "save_popover": { - "message": "現在のシーンをファイルとして保存します。" - }, - "open_popover": { - "message": "既存のファイルまたは背景画像を開きます。 背景画像は座標原点から表示されます。 (またはファイルをドロップします)" - }, - "get_link_popover": { - "incomplete": true, - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "message": "URL が長すぎるため、一部のプラットフォームでは機能しない可能性があります。 代わりに「保存」を使用してファイルを共有する必要がある場合があります。" - }, - "export_svg_warning": { - "message": "SVG にエクスポートします。 色の混合と 1 未満の相対屈折率はサポートされていません." - }, - "export_ray_count_warning": { - "incomplete": true, - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "message": "ギャラリー Web ページに移動してサンプルをロードします。" - }, - "tool_SingleRay_popover": { - "message": "2 つの点によって定義される単一光線。 (ドラッグまたはクリックして作成します。最初のポイントがソースとなり、2 番目のポイントで発射方向を決めます。)" - }, - "tool_Beam_popover": { - "incomplete": true, - "message": "A parallel or divergent beam of rays emerges from a line segment, with density controlled by the 'Ray density' slider. (Drag or click to create.)" - }, - "tool_PointSource_popover": { - "message": "光線は 1 つの点から出現し、その数は「光線密度」スライダーで調整できます。 (クリックして作成します。)" - }, - "tool_AngleSource_popover": { - "message": "指定された放射角度を持つ点光源。" - }, - "tool_Mirror_popover": { - "message": "鏡での光の反射をシミュレートします。 (ドラッグまたはクリックして作成します。)" - }, - "tool_ArcMirror_popover": { - "message": "3 つの点で定義される円の一部の形状を持つ鏡。 (ドラッグまたはクリックして作成します。最初の 2 点は円弧のエッジ間のギャップを定義し、最後の点は円弧のサイズを定義します。)" - }, - "tool_ParabolicMirror_popover": { - "message": "3 つの点で定義される放物線の形状を持つ鏡。 (ドラッグまたはクリックして作成します。)" - }, - "tool_CustomMirror_popover": { - "message": "カスタム方程式 y = f(x) によって形状が定義されるミラー。ここで (x,y) は、2 つの制御点が (-1,0) と (1,0) である変換された座標にあります。 (ドラッグまたはクリックして作成します。)" - }, - "tool_BeamSplitter_popover": { - "message": "入ってくる光の一定の割合を透過するミラー。 (ドラッグまたはクリックして作成します。)" - }, - "tool_IdealMirror_popover": { - "message": "ミラー方程式 (1/p + 1/q = 1/f) に正確に従う理想的な「曲面」ミラー。 焦点距離を直接設定できます。 (ドラッグまたはクリックして作成します。)" - }, - "tool_PlaneGlass_popover": { - "message": "表面上の光の屈折と反射をシミュレートします。 (ドラッグまたはクリックして作成します。)" - }, - "tool_CircleGlass_popover": { - "message": "中心と表面上の点によって定義される円形のガラス。 (ドラッグまたはクリックして作成します。)" - }, - "tool_CircleGrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a circular boundary. (Drag or click to create.)" - }, - "tool_Glass_popover": { - "message": "線分と円弧から構成される任意の形状のガラス。 (クリックしてセグメントを作成し、ドラッグして円弧を作成し、描画が終了したら開始点をクリックします。)" - }, - "tool_GrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a polygonal boundary. WARNING: Only simple polygons are supported, otherwise the behavior is unpredictable. (Click to create a segment, click on the starting point when finish drawing.)" - }, - "tool_IdealLens_popover": { - "message": "薄いレンズの方程式 (1/p + 1/q = 1/f) に正確に従う理想的なレンズ。 焦点距離を直接設定できます。 (ドラッグまたはクリックして作成します。)" - }, - "tool_SphericalLens_popover": { - "message": "球面レンズ (クリックして作成します。)" - }, - "tool_CustomGlass_popover": { - "message": "カスタム不等式f(x) < y < g(x)で定義される形状を持つガラスで、(x,y)は2つの制御点が(-1,0)と(1,0)である変換後の座標であるもの。(ドラッグまたはクリックで作成)" - }, - "tool_Blocker_popover": { - "message": "入射光線を吸収する線分型の遮光板です。(ドラッグまたはクリックで作成)" - }, - "tool_Aperture_popover": { - "incomplete": true, - "message": "A pair of light blockers which absorbs the incident rays. The size of the hole can be adjusted symmetrically. (Drag or click the two endpoints to create.)" - }, - "tool_CircleBlocker_popover": { - "message": "入射光線を吸収する円形の遮光板です。(ドラッグまたはクリックで作成)" - }, - "tool_DiffractionGrating_popover": { - "incomplete": true, - "message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)" - }, - "tool_Ruler_popover": { - "message": "ゼロと別の点の点からの定規。 (ドラッグまたはクリックして作成します。)" - }, - "tool_Protractor_popover": { - "message": "中心とゼロ方向の別の点から定義された分度器。 スケールは度単位です。 (ドラッグまたはクリックして作成します。)" - }, - "tool_Detector_popover": { - "message": "線分を通るエネルギー流の速度 (P)、垂直運動量流の速度 (F⊥)、および平行運動量流の速度 (F∥) を測定するためのツールです。 (ドラッグまたはクリックで線分を作成します。)単位は任意です。" - }, - "tool_Detector_info_popover": { - "incomplete": true, - "message": "" - }, - "tool_TextLabel_popover": { - "message": "テキストラベル." - }, - "tool_LineArrow_popover": { - "incomplete": true, - "message": "A line segment or arrow. (Drag or click to create.)" - }, - "tool_Drawing_popover": { - "incomplete": true, - "message": "A freehand drawing tool. (Drag to draw.)" - }, - "tool__popover": { - "message": "ドラッグでビューを移動します。(マウスの右ボタンでドラッグしても同じ機能です)。" - }, - "mode_rays_popover": { - "message": "光線を表示します。光線密度が高いと、連続しているように見えます。" - }, - "mode_extended_popover": { - "message": "光線とその延長線の両方を表示します。 オレンジは後方拡張を示し、グレーは前方拡張を示します。
「カラーのシミュレート」がオンの場合、それらはソース カラーで表示され、代わりにダッシュで区別されます。" - }, - "mode_images_popover": { - "message": "すべての画像の位置を表示します。 黄色の点は実像を示し、オレンジ色は虚像を示し、灰色 (この図には何もありません) は仮想オブジェクトを示します。 「レイ密度」が十分に高くない場合、一部のイメージは検出できないことに注意してください。
「カラーのシミュレート」がオンの場合、イメージはソース カラーで表示され、代わりにドット サイズによって区別されます。" - }, - "mode_observer_popover": { - "message": "ある位置から見た光線と画像をシミュレートします。 青い丸が観察者です。 それを横切る光線はすべて「観測された」とみなされます。 観察者は、光線が実際にどこから始まるのかを知りませんが、光線が交差する場合、ある点で光線が始まると考えるかもしれません。 光線は青、点は黄色 (現実) またはオレンジ (仮想) で表示されます。 (大きな青い点をドラッグして観察者を移動します。)
「カラーのシミュレート」がオンの場合、代わりにソース カラーで表示されます。" - }, - "simulateColors_popover": { - "incomplete": true, - "message": "Simulate colors (wavelengths) of light sources, mixture of colors, color filtering of blockers and mirrors, and chromatic dispersion of glasses. You can set those parameters for those objects when selected. To simulate color spectra, overlap rays with different wavelengths. The colors shown on the screen are only rough approximations, and can be very inaccurate when 'Ray density' is too high or too low." - }, - "rayDensity_popover": { - "incomplete": true, - "message": "Determines the number of rays to be emitted by beams and point sources. This also affects the accuracy of image detection and color rendering." - }, - "showGrid_popover": { - "message": "背景グリッドの可視性を切り替えます。" - }, - "grid_popover": { - "message": "グリッドにスナップするかどうかを切り替えます。" - }, - "lockObjs_popover": { - "message": "オブジェクトを移動できるかどうかを切り替えます。" - }, - "zoom_popover": { - "message": "パーセンテージでビューをズームします。" - }, - "help_popover": { - "incomplete": true, - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "incomplete": true, - "message": "Show help popups" - }, - "show_help_popups_popover": { - "incomplete": true, - "message": "Defines whether to show help popups when hovering over buttons. (Reload the page to take effect.)" - }, - "show_json_editor": { - "incomplete": true, - "message": "Show JSON editorBeta" - }, - "show_json_editor_popover": { - "incomplete": true, - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "incomplete": true, - "message": "Show status box" - }, - "show_status_popover": { - "incomplete": true, - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "incomplete": true, - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "incomplete": true, - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "incomplete": true, - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "incomplete": true, - "message": "Grid Size" - }, - "observer_size": { - "incomplete": true, - "message": "Observer Size" - }, - "language": { - "incomplete": true, - "message": "Language" - }, - "close": { - "incomplete": true, - "message": "Close" - }, - "advanced_help": { - "incomplete": true, - "message": "For advanced help, see the help icon in the lower-right corner." - }, - "ray_count": { - "incomplete": true, - "message": "Number of ray segments: " - }, - "total_truncation": { - "incomplete": true, - "message": "Truncated brightness: " - }, - "brightness_scale": { - "incomplete": true, - "message": "Brightness Scale: " - }, - "time_elapsed": { - "incomplete": true, - "message": "Time elapsed (ms): " - }, - "force_stopped": { - "incomplete": true, - "message": "Force stopped." - }, - "mouse_coordinates": { - "incomplete": true, - "message": "Mouse coordinates: " - }, - "modules_tutorial": { - "incomplete": true, - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "incomplete": true, - "message": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior." - }, - "import_modules": { - "incomplete": true, - "message": "Import Modules..." - }, - "import_modules_title": { - "incomplete": true, - "message": "Import Modules" - }, - "modules_url": { - "incomplete": true, - "message": "../modules/modules.html" - }, - "remove_module": { - "incomplete": true, - "message": "Remove module" - }, - "module_conflict": { - "incomplete": true, - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "incomplete": true, - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/ja/main.json b/locales/ja/main.json new file mode 100644 index 00000000..6be3e6c7 --- /dev/null +++ b/locales/ja/main.json @@ -0,0 +1,173 @@ +{ + "meta": { + "languageName": "日本語", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "光線光学系シミュレーション", + "shortName": "光線光学", + "description": "2Dの幾何学的な光学場面を作成し、シミュレーションするための無料のオープンソースのウェブアプリケーションです。" + }, + "pages": { + "home": "ホーム", + "gallery": "ギャラリー", + "about": "このソフトウェアについて", + "github": "GitHub" + }, + "homePage": { + "description": "2次元の幾何学的な光学シーンを双方向的にシミュレートすることができます。\n完全無料、ウェブベース。ソースコードは [GitHubで利用可能です。](/github).", + "launchSimulator": "シミュレーターを起動" + }, + "tools": { + "title": "ツール", + "categories": { + "lightSource": "光源", + "mirror": "鏡", + "glass": "ガラス", + "blocker": "ブロッカ", + "other": "その他" + }, + "common": { + "clickInstruction": "クリックして作成します。", + "lineInstruction": "ドラッグまたはクリックして作成します。", + "circleInstruction": "ドラッグまたはクリックして作成します。" + }, + "SingleRay": { + "title": "光線", + "description": "2 つの点によって定義される単一光線。", + "instruction": "ドラッグまたはクリックして作成します。最初のポイントがソースとなり、2 番目のポイントで発射方向を決めます。" + }, + "Beam": { + "title": "光束", + "description": "平行な光線が線分から現れ、密度は「光線密度」スライダーで調整できます。(Also supports divergent beams.)" + }, + "PointSource": { + "title": "点源", + "description": "光線は 1 つの点から出現し、その数は「光線密度」スライダーで調整できます。" + }, + "AngleSource": { + "instruction": "ドラッグまたはクリックして作成します。最初のポイントがソースとなり、2 番目のポイントで発射方向を決めます。", + "description": "指定された放射角度を持つ点光源。" + }, + "Mirror": { + "title": "分割鏡", + "description": "鏡での光の反射をシミュレートします。" + }, + "otherMirror": { + "title": "カスタム式", + "description": "カスタム方程式 y = f(x) によって形状が定義されるミラー。ここで (x,y) は、2 つの制御点が (-1,0) と (1,0) である変換された座標にあります。" + }, + "ArcMirror": { + "title": "円弧鏡", + "description": "3 つの点で定義される円の一部の形状を持つ鏡。", + "instruction": "ドラッグまたはクリックして作成します。最初の 2 点は円弧のエッジ間のギャップを定義し、最後の点は円弧のサイズを定義します。" + }, + "ParabolicMirror": { + "title": "放物線鏡", + "description": "3 つの点で定義される放物線の形状を持つ鏡。", + "instruction": "ドラッグまたはクリックして作成します。" + }, + "CustomMirror": { + "title": "カスタム式", + "description": "カスタム方程式 y = f(x) によって形状が定義されるミラー。ここで (x,y) は、2 つの制御点が (-1,0) と (1,0) である変換された座標にあります。" + }, + "IdealMirror": { + "title": "理想的なカーブ", + "description": "ミラー方程式 (1/p + 1/q = 1/f) に正確に従う理想的な「曲面」ミラー。 焦点距離を直接設定できます。" + }, + "BeamSplitter": { + "title": "ビームスプリッター", + "description": "入ってくる光の一定の割合を透過するミラー。" + }, + "PlaneGlass": { + "title": "半平面", + "description": "表面上の光の屈折と反射をシミュレートします。", + "instruction": "ドラッグまたはクリックして作成します。" + }, + "otherGlass": { + "title": "カスタム式", + "description": "カスタム不等式f(x) < y < g(x)で定義される形状を持つガラスで、(x,y)は2つの制御点が(-1,0)と" + }, + "CircleGlass": { + "title": "円", + "description": "中心と表面上の点によって定義される円形のガラス。" + }, + "Glass": { + "description": "線分と円弧から構成される任意の形状のガラス。", + "instruction": "クリックしてセグメントを作成し、ドラッグして円弧を作成し、描画が終了したら開始点をクリックします。" + }, + "CustomGlass": { + "title": "カスタム式", + "description": "カスタム不等式f(x) < y < g(x)で定義される形状を持つガラスで、(x,y)は2つの制御点が(-1,0)と" + }, + "IdealLens": { + "title": "理想的なレンズ", + "description": "薄いレンズの方程式 (1/p + 1/q = 1/f) に正確に従う理想的なレンズ。 焦点距離を直接設定できます。" + }, + "SphericalLens": { + "title": "球面レンズ", + "description": "球面レンズ" + }, + "Blocker": { + "title": "ラインブロッカー", + "description": "入射光線を吸収する線分型の遮光板です。" + }, + "CircleBlocker": { + "title": "サークルブロッカー", + "description": "入射光線を吸収する円形の遮光板です。" + }, + "Ruler": { + "title": "定規", + "description": "ゼロと別の点の点からの定規。" + }, + "Protractor": { + "title": "分度器", + "description": "中心とゼロ方向の別の点から定義された分度器。 スケールは度単位です。" + }, + "Detector": { + "title": "検出器", + "description": "線分を通るエネルギー流の速度 (P)、垂直運動量流の速度 (F⊥)、および平行運動量流の速度 (F∥) を測定するためのツールです。 単位は任意です。" + }, + "TextLabel": { + "title": "テキスト", + "description": "テキストラベル." + }, + "moveView": { + "title": "ビューを移動する", + "description": "ドラッグでビューを移動します。(マウスの右ボタンでドラッグしても同じ機能です)。" + } + }, + "view": { + "title": "ビュー", + "rays": { + "title": "光線", + "description": "光線を表示します。光線密度が高いと、連続しているように見えます。" + }, + "extended": { + "title": "拡張光線", + "description": "光線とその延長線の両方を表示します。 オレンジは後方拡張を示し、グレーは前方拡張を示します。", + "simulateColorsNote": "「カラーのシミュレート」がオンの場合、それらはソース カラーで表示され、代わりにダッシュで区別されます。" + }, + "images": { + "title": "すべての画像", + "description": "すべての画像の位置を表示します。 黄色の点は実像を示し、オレンジ色は虚像を示し、灰色 (この図には何もありません) は仮想オブジェクトを示します。 「レイ密度」が十分に高くない場合、一部のイメージは検出できないことに注意してください。", + "simulateColorsNote": "「カラーのシミュレート」がオンの場合、イメージはソース カラーで表示され、代わりにドット サイズによって区別されます。" + }, + "observer": { + "title": "観察者が見た", + "description": "ある位置から見た光線と画像をシミュレートします。 青い丸が観察者です。 それを横切る光線はすべて「観測された」とみなされます。 観察者は、光線が実際にどこから始まるのかを知りませんが、光線が交差する場合、ある点で光線が始まると考えるかもしれません。 光線は青、点は黄色 (現実) またはオレンジ (仮想) で表示されます。", + "simulateColorsNote": "「カラーのシミュレート」がオンの場合、代わりにソース カラーで表示されます。", + "instruction": "大きな青い点をドラッグして観察者を移動します。" + } + }, + "simulateColors": { + "title": "色のシミュレーション", + "description": "光源の色(波長)、色の混色、ガラスの波長分散をシミュレーションします。" + }, + "languageDropdown": { + "title": "言語: {{language}}", + "translatedFraction": "{{fraction}} 翻訳済み" + } +} \ No newline at end of file diff --git a/locales/ja/simulator.json b/locales/ja/simulator.json new file mode 100644 index 00000000..cd34be73 --- /dev/null +++ b/locales/ja/simulator.json @@ -0,0 +1,114 @@ +{ + "welcome": { + "title": "光学シミュレーションの世界へようこそ", + "instruction": "光学部品を追加するには、ツールを選択し、空白部分をクリックします。\n例を読み込むには [ギャラリーページに移動してください。](/gallery)." + }, + "common": { + "saveButton": "保存", + "cancelButton": "キャンセル" + }, + "file": { + "title": "ファイル", + "undo": { + "title": "元に戻す" + }, + "redo": { + "title": "やり直し" + }, + "reset": { + "title": "リセット" + }, + "save": { + "title": "保存" + }, + "open": { + "title": "開く", + "description": "既存のファイルまたは背景画像を開きます。 背景画像は座標原点から表示されます。 (またはファイルをドロップします)" + }, + "viewGallery": { + "title": "ギャラリーを見る", + "description": "ギャラリー Web ページに移動してサンプルをロードします。" + } + }, + "settings": { + "title": "設定", + "rayDensity": { + "title": "光線密度" + }, + "layoutAids": { + "showGrid": "グリッド", + "snapToGrid": "グリッドにスナップ", + "lockObjs": "オブジェクトを固定" + }, + "zoom": { + "title": "ズーム" + }, + "language": { + "title": "言語" + } + }, + "objBar": { + "applyToAll": { + "title": "すべてに適用" + }, + "duplicate": { + "title": "複製" + }, + "delete": { + "title": "消去" + } + }, + "sceneObjs": { + "common": { + "brightness": "明るさ", + "wavelength": "波長", + "emisAngle": "放射角度", + "random": "ランダム", + "lambert": "ランバーシアン", + "focalLength": "焦点距離" + }, + "AngleSource": { + "symmetric": "対称" + }, + "BaseFilter": { + "filter": "フィルタ", + "bandwidth": "帯域幅", + "invert": "反転" + }, + "BeamSplitter": { + "transRatio": "透過率" + }, + "BaseGlass": { + "refIndex": "屈折率", + "refIndexInfo": { + "effective": "もし(絶対)屈折率n₁でシミュレートされる物体があったとしても、別の屈折率n₀のガラスの中に置かれる場合、ここで屈折率をn₁/n₀に設定する必要があります。複数のガラスが重なり合うような複雑なケースでは、重なり合う領域の実効反射率は、個々のものの反射率の積に等しくなります。" + } + }, + "TextLabel": { + "fontSize": "フォントサイズ", + "font": "フォント", + "fontStyle": "スタイル", + "alignment": "文字揃え", + "smallCaps": "スモールキャピタル", + "angle": "角度" + }, + "CropBox": { + "svgWarning": "SVG にエクスポートします。 色の混合と 1 未満の相対屈折率はサポートされていません." + } + }, + "saveModal": { + "title": "保存", + "fileName": "名前" + }, + "languageModal": { + "title": "言語", + "translatedFraction": "翻訳済み", + "helpTranslate": "このアプリの翻訳にご協力ください" + }, + "generalWarnings": { + "shareLinkTooLong": "URL が長すぎるため、一部のプラットフォームでは機能しない可能性があります。 代わりに「保存」を使用してファイルを共有する必要がある場合があります。" + }, + "footer": { + "processing": "処理中...停止するにはここをクリックしてください." + } +} \ No newline at end of file diff --git a/locales/ko.json b/locales/ko.json deleted file mode 100644 index 0d9dd9da..00000000 --- a/locales/ko.json +++ /dev/null @@ -1,970 +0,0 @@ -{ - "appName": { - "message": "광선 광학 시뮬레이션" - }, - "appShortName": { - "message": "광선 광학" - }, - "appDesc": { - "message": "2D 기하 광학 생성 및 시뮬레이션을 위한 무료 오픈소스 웹 기반 앱입니다." - }, - "homepage_desc": { - "message": "2D 기하 광학을 시뮬레이션할 수 있습니다.
무료이며 웹 기반입니다. 소스 코드: GitHub 에서 사용 가능." - }, - "launch_simulator": { - "message": "시뮬레이터 실행" - }, - "home": { - "message": "홈" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/ko/" - }, - "gallery": { - "message": "갤러리" - }, - "gallery_url": { - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "message": "광선 광학 시뮬레이션에 오신 것을 환영합니다.
광학 요소를 추가하려면 도구를 선택한 후 빈 공간을 클릭하십시오.
예제를 불러오려면 갤러리 페이지로 이동하십시오." - }, - "loading_msg": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
Loading scene from URL... Please wait." - }, - "toolbar_title": { - "message": "도구: " - }, - "toolname_SingleRay": { - "message": "단일 광선" - }, - "toolname_AngleSource": { - "message": "점 광원" - }, - "toolname_PointSource": { - "message": "점 광원" - }, - "toolname_Beam": { - "message": "빔 (평행광)" - }, - "toolname_mirror_": { - "message": "거울" - }, - "toolname_Mirror": { - "message": "거울" - }, - "toolname_ArcMirror": { - "message": "거울" - }, - "toolname_ParabolicMirror": { - "message": "거울" - }, - "toolname_CustomMirror": { - "message": "거울" - }, - "toolname_IdealMirror": { - "message": "이상적인 곡면 거울 (Ideal curved mirror)" - }, - "toolname_glass_": { - "message": "유리" - }, - "toolname_blocker_": { - "message": "차단기" - }, - "toolname_BeamSplitter": { - "message": "빔 스플리터" - }, - "toolname_PlaneGlass": { - "message": "유리" - }, - "toolname_CircleGlass": { - "message": "유리" - }, - "toolname_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_Glass": { - "message": "유리" - }, - "toolname_GrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_IdealLens": { - "message": "이상적인 렌즈 (Ideal lens)" - }, - "toolname_SphericalLens": { - "message": "구면 렌즈" - }, - "toolname_CustomGlass": { - "message": "유리" - }, - "toolname_Blocker": { - "message": "선형 차단기" - }, - "toolname_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "toolname_CircleBlocker": { - "message": "원형 차단기" - }, - "toolname_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "toolname_Ruler": { - "message": "자" - }, - "toolname_Protractor": { - "message": "각도기" - }, - "tool_Detector": { - "message": "검출기 (Detector)" - }, - "toolname_Detector": { - "message": "검출기 (Detector)" - }, - "toolname_TextLabel": { - "message": "텍스트" - }, - "toolname_LineArrow": { - "incomplete": true, - "message": "Line" - }, - "toolname_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "toolname_Handle": { - "incomplete": true, - "message": "Handle" - }, - "toolname_CropBox": { - "incomplete": true, - "message": "Export" - }, - "toolname_ModuleObj": { - "incomplete": true, - "message": "ModuleBeta" - }, - "tool_more_": { - "message": "더 보기" - }, - "toolname_": { - "message": "화면 이동" - }, - "modebar_title": { - "message": "보기" - }, - "modename_light": { - "message": "광선" - }, - "modename_extended_light": { - "message": "연장된 광선" - }, - "modename_images": { - "message": "모든 이미지" - }, - "modename_observer": { - "message": "관찰자가 보는 이미지" - }, - "simulateColors": { - "message": "색상 (파장) 시뮬레이션" - }, - "File: ": { - "message": "파일" - }, - "Tools: ": { - "message": "도구" - }, - "tool_SingleRay": { - "message": "광선" - }, - "tool_Beam": { - "message": "빔 (평행광)" - }, - "tool_PointSource": { - "message": "점 광원 (360°)" - }, - "tool_AngleSource": { - "message": "점 광원 (<360°)" - }, - "tool_PointSource_": { - "message": "점 광원" - }, - "tool_lightSource_": { - "message": "광원" - }, - "tool_mirror_": { - "message": "거울" - }, - "tool_Mirror": { - "message": "부분 (Segment)" - }, - "tool_ArcMirror": { - "message": "원형 호" - }, - "tool_ParabolicMirror": { - "message": "포물면" - }, - "tool_CustomMirror": { - "message": "사용자 정의 수식" - }, - "tool_BeamSplitter": { - "message": "빔 스플리터" - }, - "tool_IdealMirror": { - "message": "이상 곡면 거울 (Ideal Curved)" - }, - "tool_glass_": { - "message": "유리" - }, - "tool_blocker_": { - "message": "차단기" - }, - "tool_PlaneGlass": { - "message": "반 평면 (Half-plane)" - }, - "tool_CircleGlass": { - "message": "원형" - }, - "tool_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index circle" - }, - "tool_Glass": { - "incomplete": true, - "message": "Polygon / Circular Arcs" - }, - "tool_GrinGlass": { - "incomplete": true, - "message": "Gradient-index polygon" - }, - "tool_IdealLens": { - "message": "이상적인 렌즈 (Ideal lens)" - }, - "tool_SphericalLens": { - "message": "구면 렌즈" - }, - "tool_CustomGlass": { - "message": "사용자 정의 수식" - }, - "tool_Blocker": { - "message": "선형 차단기" - }, - "tool_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "tool_CircleBlocker": { - "message": "원형 차단기" - }, - "tool_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "tool_Ruler": { - "message": "자" - }, - "tool_Protractor": { - "message": "각도기" - }, - "tool_TextLabel": { - "message": "텍스트" - }, - "tool_LineArrow": { - "incomplete": true, - "message": "Line / Arrow" - }, - "tool_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "tool_": { - "message": "화면 이동" - }, - "View: ": { - "message": "보기" - }, - "Settings: ": { - "message": "설정" - }, - "moresettings": { - "message": "더 보기" - }, - "mode_rays": { - "message": "광선 모드" - }, - "mode_extended": { - "message": "광선 연장 모드" - }, - "mode_images": { - "message": "전체 이미지 모드" - }, - "mode_observer": { - "message": "관측자가 보는 이미지 모드" - }, - "zoom": { - "message": "확대/축소" - }, - "help": { - "message": "도움말" - }, - "rayDensity": { - "message": "광선 밀도" - }, - "raydensity": { - "message": "광선 밀도" - }, - "undo": { - "message": "실행 취소" - }, - "redo": { - "message": "재실행" - }, - "reset": { - "message": "재설정" - }, - "save": { - "message": "저장" - }, - "rename": { - "incomplete": true, - "message": "Rename" - }, - "get_link": { - "incomplete": true, - "message": "Copy Shareable Link" - }, - "export_svg": { - "incomplete": true, - "message": "Export as PNG/SVG" - }, - "view_gallery": { - "message": "갤러리 보기" - }, - "save_name": { - "message": "이름" - }, - "save_cancel": { - "message": "취소" - }, - "save_description": { - "incomplete": true, - "message": "" - }, - "open": { - "message": "열기" - }, - "layoutaids": { - "message": "레이아웃 도구" - }, - "lockObjs": { - "message": "사물 고정" - }, - "showGrid": { - "message": "격자" - }, - "snapToGrid": { - "message": "격자선에 물리기" - }, - "snaptogrid": { - "message": "격자선에 물리기" - }, - "length_unit_popover": { - "incomplete": true, - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "incomplete": true, - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "incomplete": true, - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "message": "밝기" - }, - "wavelength": { - "message": "파장 (nm)" - }, - "dichroic": { - "message": "이색 (Dichroic)" - }, - "filter": { - "message": "필터" - }, - "bandwidth": { - "message": "대역폭 (Bandwidth) (nm)" - }, - "invert": { - "message": "반전" - }, - "emisAngle": { - "message": "방출 각 (°)" - }, - "mirrored": { - "incomplete": true, - "message": "Mirrored" - }, - "lineDensity": { - "incomplete": true, - "message": "Lines/mm" - }, - "slitRatio": { - "incomplete": true, - "message": "Slit width / line spacing" - }, - "customBrightness": { - "incomplete": true, - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "incomplete": true, - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "message": "대칭" - }, - "eqn_note": { - "incomplete": true, - "message": "" - }, - "symbolic_grin": { - "incomplete": true, - "message": "Symbolic body-merging" - }, - "grin_refractive_index": { - "incomplete": true, - "message": "" - }, - "symbolic_grin_note_popover": { - "incomplete": true, - "message": "

This toggle applies to all GRIN objects in the simulation.

This simulator has currently two implementations of light propagation between different mediums, for GRIN objects - numerical and symbolic (see 'multRefIndex' and 'devRefIndex' functions in 'CircleGrinGlass.js').

The numerical implementation is faster but doesn't always work properly (depending on the specific case) in scenarios when used with more than one GRIN object, such that at least one of them has a refractive index function which is not defined in the entire plane, while the symbolic implementation is slower but robust to such problems.

" - }, - "focalLength": { - "message": "초점 거리" - }, - "cartesianSign": { - "message": "직교좌표계 부호 변환" - }, - "refIndex": { - "message": "굴절률*" - }, - "radii_of_curvature": { - "incomplete": true, - "message": "Radii of Curvature" - }, - "focal_distances": { - "incomplete": true, - "message": "Focal Distances" - }, - "refIndex_origin": { - "incomplete": true, - "message": "Origin of n(x,y)" - }, - "stepSize": { - "incomplete": true, - "message": "Numerical solver step size" - }, - "intersectTol": { - "incomplete": true, - "message": "Intersection tolerance" - }, - "random": { - "message": "랜덤" - }, - "lambert": { - "message": "램버시안 (Lambertian)" - }, - "diameter": { - "incomplete": true, - "message": "Diameter" - }, - "irradMap": { - "incomplete": true, - "message": "Irradiance Map" - }, - "binSize": { - "incomplete": true, - "message": "Bin Size" - }, - "scaleInterval": { - "incomplete": true, - "message": "Scale interval" - }, - "exportData": { - "incomplete": true, - "message": "Export data" - }, - "demodulize": { - "incomplete": true, - "message": "Demodulize" - }, - "fontSize": { - "message": "폰트 크기" - }, - "font": { - "message": "폰트" - }, - "fontStyle": { - "message": "스타일" - }, - "normal": { - "incomplete": true, - "message": "Normal" - }, - "bold": { - "incomplete": true, - "message": "Bold" - }, - "italic": { - "incomplete": true, - "message": "Italic" - }, - "bolditalic": { - "incomplete": true, - "message": "Bold Italic" - }, - "oblique": { - "incomplete": true, - "message": "Oblique" - }, - "boldoblique": { - "incomplete": true, - "message": "Bold Oblique" - }, - "alignment": { - "message": "정렬" - }, - "left": { - "incomplete": true, - "message": "Left" - }, - "center": { - "incomplete": true, - "message": "Centre" - }, - "right": { - "incomplete": true, - "message": "Right" - }, - "text_here": { - "incomplete": true, - "message": "Text Here" - }, - "smallCaps": { - "message": "Small Caps" - }, - "angle": { - "message": "각도 (°)" - }, - "arrow": { - "incomplete": true, - "message": "Forward arrow" - }, - "backArrow": { - "incomplete": true, - "message": "Backward arrow" - }, - "stop_drawing": { - "incomplete": true, - "message": "Finish Drawing" - }, - "cropBoxSize": { - "incomplete": true, - "message": "Crop Box Size" - }, - "format": { - "incomplete": true, - "message": "Format" - }, - "width": { - "incomplete": true, - "message": "Width" - }, - "rayCountLimit": { - "incomplete": true, - "message": "Ray count limit" - }, - "transformation": { - "incomplete": true, - "message": "TransformationBeta" - }, - "default": { - "incomplete": true, - "message": "Default" - }, - "translation": { - "incomplete": true, - "message": "Translation" - }, - "xTranslation": { - "incomplete": true, - "message": "X Translation" - }, - "yTranslation": { - "incomplete": true, - "message": "Y Translation" - }, - "rotation": { - "incomplete": true, - "message": "Rotation" - }, - "scaling": { - "incomplete": true, - "message": "Scaling" - }, - "beam_warning": { - "message": "발산하거나 랜덤한 빔의 경우 정상적으로 인식되지 않거나 작동하지 않을 수 있습니다." - }, - "image_detection_warning": { - "incomplete": true, - "message": "This tool does not support image detection." - }, - "non_simulateColors_warning": { - "incomplete": true, - "message": "This tool only works when \"Simulate Color\" is on." - }, - "brightness_note_popover": { - "message": "

'광선 밀도'가 충분히 높을 때 유효합니다.

방출되는 광선의 개수를 조절하려면 '광선 밀도' 슬라이더를 조절하십시오.

" - }, - "refIndex_note_popover": { - "message": "

*다른 매질 내부에 있다면 상대 굴절률

이 객체가 (절대) 굴절률 n₁으로 시뮬레이션되어야 하는데 굴절률이 n₀인 다른 매질 내부에 있다면 상대 굴절률인 n₁/n₀ 를 입력해야합니다. 여러 장의 매질이 겹쳐진 복잡한 경우에는 겹친 영역의 실질적인 굴절률 (effective refractive index)은 매질 각각의 굴절률의 곱과 같습니다.

" - }, - "stepSize_note_popover": { - "incomplete": true, - "message": "

Step size of Euler's method for solving the eikonal ray equation - see 'step' function and documentation inside the 'CircleGrinGlass.js' file, for more information.

" - }, - "eps_CircleGrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length]^2.

This numerical tolerance is used in the functions 'isOutsideGlass', 'isInsideGlass' and 'isOnBoundary', inside the 'CircleGrinGlass.js' file.

" - }, - "eps_GrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length].

This numerical tolerance is used in the functions 'isOnBoundary' and 'countIntersections', inside the 'GrinGlass.js' file.

" - }, - "cauchyCoeff": { - "message": "코시 계수 (Cauchy coefficient)" - }, - "transRatio": { - "message": "전송률" - }, - "applytoall": { - "message": "전체에 적용" - }, - "duplicate": { - "message": "복제" - }, - "delete": { - "message": "삭제" - }, - "unselect": { - "message": "선택 해제" - }, - "unselect_popover": { - "message": "이 물체의 선택을 해제합니다. (또는 빈 영역에 우클릭합니다.)" - }, - "showadvanced": { - "message": "추가 옵션" - }, - "processing": { - "message": "작업중... 중단하려면 클릭." - }, - "contribute": { - "message": "기여하기" - }, - "github": { - "message": "GitHub" - }, - "about": { - "message": "이 앱에 대하여" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "message": "이 앱의 번역 참여" - }, - "translated": { - "message": "번역 됨" - }, - "undo_popover": { - "message": "마지막 작업 취소. (Ctrl+Z)" - }, - "redo_popover": { - "message": "마지막 작업 재실행. (Ctrl+Y)" - }, - "reset_popover": { - "message": "모든 작업 초기화." - }, - "save_popover": { - "message": "현재 결과를 파일로 저장." - }, - "open_popover": { - "message": "기존 파일이나 배경 이미지 열기. 배경 이미지는 좌표 원점을 기준으로 표시됩니다. (또는 파일을 올려놓으십시오.)" - }, - "get_link_popover": { - "incomplete": true, - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "message": "URL이 너무 길어서 일부 플랫폼에서 작동하지 않을 수 있습니다. 이 경우 \"저장\"을 사용해 파일을 공유하십시오." - }, - "export_svg_warning": { - "message": "SVG로 추출하기. 색상 혼합 및 1 미만의 상대 굴절율은 지원되지 않습니다." - }, - "export_ray_count_warning": { - "incomplete": true, - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "message": "예제를 불러오기 위해 갤러리로 이동." - }, - "tool_SingleRay_popover": { - "message": "두 점으로 정의된 단일 광선. (드래그 또는 클릭하여 생성. 첫 번째 지점에서 두 번째 지점을 향하는 방향.)" - }, - "tool_Beam_popover": { - "message": "선분으로 나타나는 평행 또는 발산하는 광선 빔. 밀도 조절은 '광선 밀도' 슬라이더를 통해 조절. (드래그 또는 클릭하여 생성.)" - }, - "tool_PointSource_popover": { - "message": "점 광원에서 발생하는 광선. 밀도 조절은 '광선 밀도' 슬라이더를 통해 조절. (드래그 또는 클릭하여 생성.)" - }, - "tool_AngleSource_popover": { - "message": "주어진 각도 범위에서 방출하는 점 광원." - }, - "tool_Mirror_popover": { - "message": "거울에서의 반사 시뮬레이션 (드래그 또는 클릭하여 생성)" - }, - "tool_ArcMirror_popover": { - "message": "구면 거울. (세 개의 점으로 정의된 원) (드래그 또는 클릭하여 생성. 첫 두 점은 호의 가장자리 사이 간격을 정의하고, 마지막 점은 호의 크기를 정의합니다.)" - }, - "tool_ParabolicMirror_popover": { - "message": "포물면 거울. (세 개의 점으로 정의된 포물선) (드래그 또는 클릭하여 생성.)" - }, - "tool_CustomMirror_popover": { - "message": "사용자 정의 수식 y=f(x) 에 의해 정의된 거울. (x, y)는 두 제어점이 각각 (-1, 0)과 (1, 0)이 되도록 변환된 좌표입니다. (드래그 또는 클릭하여 생성.)" - }, - "tool_BeamSplitter_popover": { - "message": "입사광의 일부를 투과시키는 거울. (드래그 또는 클릭하여 생성.)" - }, - "tool_IdealMirror_popover": { - "message": "거울 방정식 (1/p + 1/q = 1/f) 를 따르는 이상적인 곡면 거울. 초점 거리를 설정할 수 있습니다. (드래그 또는 클릭하여 생성.)" - }, - "tool_PlaneGlass_popover": { - "message": "표면에서의 굴절 및 반사 시뮬레이션. (드래그 또는 클릭하여 생성.)" - }, - "tool_CircleGlass_popover": { - "message": "구면 유리. (중심과 표면의 한 점으로 정의된 원) (드래그 또는 클릭하여 생성.)" - }, - "tool_CircleGrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a circular boundary. (Drag or click to create.)" - }, - "tool_Glass_popover": { - "message": "선분과 원호로 구성된 다양한 형태의 유리 (선분을 생성하려면 클릭, 호를 만들려면 드래그, 그리기가 끝나면 시작점을 클릭.)" - }, - "tool_GrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a polygonal boundary. WARNING: Only simple polygons are supported, otherwise the behavior is unpredictable. (Click to create a segment, click on the starting point when finish drawing.)" - }, - "tool_IdealLens_popover": { - "message": "얇은 렌즈 방정식 (1/p + 1/q = 1/f) 를 따르는 이상적인 렌즈. 초점 거리를 설정할 수 있습니다. (드래그 또는 클릭하여 생성.)" - }, - "tool_SphericalLens_popover": { - "message": "구면 렌즈. (클릭하여 생성.)" - }, - "tool_CustomGlass_popover": { - "message": "사용자 정의 수식 f(x) < y < g(x) 에 의해 정의된 유리. (x, y)는 두 제어점이 각각 (-1, 0)과 (1, 0)이 되도록 변환된 좌표입니다. (드래그 또는 클릭하여 생성.)" - }, - "tool_Blocker_popover": { - "message": "입사 광선을 흡수하는 선형 차단기입니다. (드래그 또는 클릭하여 생성.)" - }, - "tool_Aperture_popover": { - "incomplete": true, - "message": "A pair of light blockers which absorbs the incident rays. The size of the hole can be adjusted symmetrically. (Drag or click the two endpoints to create.)" - }, - "tool_CircleBlocker_popover": { - "message": "입사 광선을 흡수하는 원형 차단기입니다. (드래그 또는 클릭하여 생성.)" - }, - "tool_DiffractionGrating_popover": { - "incomplete": true, - "message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)" - }, - "tool_Ruler_popover": { - "message": "눈금자입니다. (시작점이 0) (드래그 또는 클릭하여 생성.)" - }, - "tool_Protractor_popover": { - "message": "도 단위의 각도기입니다. (시작점이 중심) (드래그 또는 클릭하여 생성.)" - }, - "tool_Detector_popover": { - "message": "선분을 통해 전달되는 에너지 흐름 (P), 수직 방향 momentum flow (F⊥), 평행 방향 memontum flow (F∥) 을 측정하는 도구입니다. 단위는 임의값 (A.U.) 입니다.." - }, - "tool_Detector_info_popover": { - "incomplete": true, - "message": "" - }, - "tool_TextLabel_popover": { - "message": "텍스트 추가" - }, - "tool_LineArrow_popover": { - "incomplete": true, - "message": "A line segment or arrow. (Drag or click to create.)" - }, - "tool_Drawing_popover": { - "incomplete": true, - "message": "A freehand drawing tool. (Drag to draw.)" - }, - "tool__popover": { - "message": "화면을 이동하려면 드래그하십시오. (이 버튼을 누르지 않고, 마우스 우클릭 드래그를 사용해도 됩니다.)" - }, - "mode_rays_popover": { - "message": "광선을 나타냅니다. 광선 밀도가 높으면 연속적인 것 처럼 나타납니다." - }, - "mode_extended_popover": { - "message": "광선과 연장선을 모두 표시합니다. 회색은 진행 방향을, 주황색은 진행 방향의 반대 방향을 나타냅니다.
'색상 (파장) 시뮬레이션'이 켜져 있으면 원본 색상으로 표시되고 점선으로 나타냅니다." - }, - "mode_images_popover": { - "message": "모든 상의 위치를 표시합니다. 노란색 점은 실상, 주황색 점은 허상, 회색 (예시 그림에는 없음) 점은 가상 객체를 나타냅니다. '광선 밀도'가 충분히 높지 않으면 일부 이미지를 감지할 수 없습니다.
'색상 (파장) 시뮬레이션'이 켜져 있으면 원본 색상으로 표시되고 점 크기로 구분합니다." - }, - "mode_observer_popover": { - "message": "특정 위치에서 보는 광선과 상을 시뮬레이션합니다. 파란색 원은 관찰자이며 이것을 지나는 광선은 '관찰된 것'으로 간주됩니다. '관찰된 광선'으로부터 관찰자는 광선이 어디에선가 시작되었다고 생각할 수는 있지만, 실제로 어느 위치에서 시작된 광선인지는 알 수 없습니다. 광선들은 파란색으로, 실상과 허상은 각각 노란색과 주황색 점으로 나타납니다. (관찰자의 위치를 옮기려면 큰 파란 점을 드래그하십시오.)
'색상 (파장) 시뮬레이션'이 켜져 있으면 원본 색상으로 표시됩니다." - }, - "simulateColors_popover": { - "message": "광원의 색상 (파장), 색상 혼합, 차단기와 거울에 의한 파장 필터링, 매질의 색 분산을 시뮬레이션합니다. 개체를 선택할 때 이러한 변수를 설정할 수 있습니다. 색상 스펙트럼을 시뮬레이션 하려면 여러 파장의 광선을 겹치십시오. 화면에 표시되는 색상은 대략적인 근사이며, 광선 밀도가 너무 높거나 낮을 시 매우 부정확할 수 있습니다. " - }, - "rayDensity_popover": { - "message": "빔이나 점광원으로부터 발생하는 광선의 개수를 결정합니다. 상 검출과 색 표현에도 영향을 미칩니다." - }, - "showGrid_popover": { - "message": "배경 격자의 가시성을 결정합니다. " - }, - "grid_popover": { - "message": "객체를 위치시킬 때 격자선에 물릴지 결정합니다." - }, - "lockObjs_popover": { - "message": "객체의 이동 가능 여부를 결정합니다." - }, - "zoom_popover": { - "message": "화면 확대 비율을 퍼센트로 결정합니다." - }, - "help_popover": { - "incomplete": true, - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "message": "도움말 팝업 표시" - }, - "show_help_popups_popover": { - "message": "버튼 위를 지날 때 도움말을 표시할 지 결정합니다. (효과 반영을 위해 페이지를 다시 불러옵니다.)" - }, - "show_json_editor": { - "incomplete": true, - "message": "Show JSON editorBeta" - }, - "show_json_editor_popover": { - "incomplete": true, - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "incomplete": true, - "message": "Show status box" - }, - "show_status_popover": { - "incomplete": true, - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "incomplete": true, - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "incomplete": true, - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "incomplete": true, - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "incomplete": true, - "message": "Grid Size" - }, - "observer_size": { - "incomplete": true, - "message": "Observer Size" - }, - "language": { - "message": "언어" - }, - "close": { - "message": "닫기" - }, - "advanced_help": { - "message": "추가적인 설명이 필요한 경우 우측 하단의 도움말 아이콘을 클릭하십시오." - }, - "ray_count": { - "incomplete": true, - "message": "Number of ray segments: " - }, - "total_truncation": { - "incomplete": true, - "message": "Truncated brightness: " - }, - "brightness_scale": { - "incomplete": true, - "message": "Brightness Scale: " - }, - "time_elapsed": { - "incomplete": true, - "message": "Time elapsed (ms): " - }, - "force_stopped": { - "incomplete": true, - "message": "Force stopped." - }, - "mouse_coordinates": { - "incomplete": true, - "message": "Mouse coordinates: " - }, - "modules_tutorial": { - "incomplete": true, - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "incomplete": true, - "message": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior." - }, - "import_modules": { - "incomplete": true, - "message": "Import Modules..." - }, - "import_modules_title": { - "incomplete": true, - "message": "Import Modules" - }, - "modules_url": { - "incomplete": true, - "message": "../modules/modules.html" - }, - "remove_module": { - "incomplete": true, - "message": "Remove module" - }, - "module_conflict": { - "incomplete": true, - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "incomplete": true, - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/ko/main.json b/locales/ko/main.json new file mode 100644 index 00000000..553a1c12 --- /dev/null +++ b/locales/ko/main.json @@ -0,0 +1,175 @@ +{ + "meta": { + "languageName": "한국어", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "광선 광학 시뮬레이션", + "shortName": "광선 광학", + "description": "2D 기하 광학 생성 및 시뮬레이션을 위한 무료 오픈소스 웹 기반 앱입니다." + }, + "pages": { + "home": "홈", + "gallery": "갤러리", + "about": "이 앱에 대하여", + "github": "GitHub" + }, + "homePage": { + "description": "2D 기하 광학을 시뮬레이션할 수 있습니다.\n무료이며 웹 기반입니다. 소스 코드: [ GitHub 에서 사용 가능](/github).", + "launchSimulator": "시뮬레이터 실행" + }, + "tools": { + "title": "도구", + "categories": { + "lightSource": "광원", + "mirror": "거울", + "glass": "유리", + "blocker": "차단기", + "other": "더 보기" + }, + "common": { + "clickInstruction": "드래그 또는 클릭하여 생성.", + "lineInstruction": "드래그 또는 클릭하여 생성", + "circleInstruction": "드래그 또는 클릭하여 생성." + }, + "SingleRay": { + "title": "광선", + "description": "두 점으로 정의된 단일 광선.", + "instruction": "드래그 또는 클릭하여 생성. 첫 번째 지점에서 두 번째 지점을 향하는 방향." + }, + "Beam": { + "title": "빔 (평행광)", + "description": "선분으로 나타나는 평행 또는 발산하는 광선 빔. 밀도 조절은 '광선 밀도' 슬라이더를 통해 조절." + }, + "PointSource": { + "title": "점 광원", + "description": "점 광원에서 발생하는 광선. 밀도 조절은 '광선 밀도' 슬라이더를 통해 조절." + }, + "AngleSource": { + "instruction": "드래그 또는 클릭하여 생성. 첫 번째 지점에서 두 번째 지점을 향하는 방향.", + "description": "주어진 각도 범위에서 방출하는 점 광원." + }, + "Mirror": { + "title": "부분 (Segment)", + "description": "거울에서의 반사 시뮬레이션" + }, + "otherMirror": { + "title": "사용자 정의 수식", + "description": "사용자 정의 수식 y=f(x) 에 의해 정의된 거울. (x, y)는 두 제어점이 각각 (-1, 0)과 (1, 0)이 되도록 변환된 좌표입니다." + }, + "ArcMirror": { + "title": "원형 호", + "description": "구면 거울. (세 개의 점으로 정의된 원)", + "instruction": "드래그 또는 클릭하여 생성. 첫 두 점은 호의 가장자리 사이 간격을 정의하고, 마지막 점은 호의 크기를 정의합니다." + }, + "ParabolicMirror": { + "title": "포물면", + "description": "포물면 거울. (세 개의 점으로 정의된 포물선)", + "instruction": "드래그 또는 클릭하여 생성." + }, + "CustomMirror": { + "title": "사용자 정의 수식", + "description": "사용자 정의 수식 y=f(x) 에 의해 정의된 거울. (x, y)는 두 제어점이 각각 (-1, 0)과 (1, 0)이 되도록 변환된 좌표입니다." + }, + "IdealMirror": { + "title": "이상 곡면 거울 (Ideal Curved)", + "description": "거울 방정식 (1/p + 1/q = 1/f) 를 따르는 이상적인 곡면 거울. 초점 거리를 설정할 수 있습니다." + }, + "BeamSplitter": { + "title": "빔 스플리터", + "description": "입사광의 일부를 투과시키는 거울." + }, + "PlaneGlass": { + "title": "반 평면 (Half-plane)", + "description": "표면에서의 굴절 및 반사 시뮬레이션.", + "instruction": "드래그 또는 클릭하여 생성." + }, + "otherGlass": { + "title": "사용자 정의 수식", + "description": "사용자 정의 수식 f(x) < y < g(x) 에 의해 정의된 유리. (x, y)는 두 제어점이 각각 (-1, 0)과 (1, 0)이 되도록 변환된 좌표입니다." + }, + "CircleGlass": { + "title": "원형", + "description": "구면 유리. (중심과 표면의 한 점으로 정의된 원)" + }, + "Glass": { + "description": "선분과 원호로 구성된 다양한 형태의 유리", + "instruction": "선분을 생성하려면 클릭, 호를 만들려면 드래그, 그리기가 끝나면 시작점을 클릭." + }, + "CustomGlass": { + "title": "사용자 정의 수식", + "description": "사용자 정의 수식 f(x) < y < g(x) 에 의해 정의된 유리. (x, y)는 두 제어점이 각각 (-1, 0)과 (1, 0)이 되도록 변환된 좌표입니다." + }, + "IdealLens": { + "title": "이상적인 렌즈 (Ideal lens)", + "description": "얇은 렌즈 방정식 (1/p + 1/q = 1/f) 를 따르는 이상적인 렌즈. 초점 거리를 설정할 수 있습니다." + }, + "SphericalLens": { + "title": "구면 렌즈", + "description": "구면 렌즈." + }, + "Blocker": { + "title": "선형 차단기", + "description": "입사 광선을 흡수하는 선형 차단기입니다." + }, + "CircleBlocker": { + "title": "원형 차단기", + "description": "입사 광선을 흡수하는 원형 차단기입니다." + }, + "Ruler": { + "title": "자", + "description": "눈금자입니다. (시작점이 0)" + }, + "Protractor": { + "title": "각도기", + "description": "도 단위의 각도기입니다. (시작점이 중심)" + }, + "Detector": { + "title": "검출기 (Detector)", + "description": "선분을 통해 전달되는 에너지 흐름 (P), 수직 방향 momentum flow (F⊥), 평행 방향 memontum flow (F∥) 을 측정하는 도구입니다. 단위는 임의값 입니다.." + }, + "TextLabel": { + "title": "텍스트", + "description": "텍스트 추가" + }, + "moveView": { + "title": "화면 이동", + "description": "화면을 이동하려면 드래그하십시오. (이 버튼을 누르지 않고, 마우스 우클릭 드래그를 사용해도 됩니다.)" + } + }, + "view": { + "title": "보기", + "rays": { + "title": "광선 모드", + "description": "광선을 나타냅니다. 광선 밀도가 높으면 연속적인 것 처럼 나타납니다." + }, + "extended": { + "title": "광선 연장 모드", + "description": "광선과 연장선을 모두 표시합니다. 회색은 진행 방향을, 주황색은 진행 방향의 반대 방향을 나타냅니다.", + "simulateColorsNote": "'색상 (파장) 시뮬레이션'이 켜져 있으면 원본 색상으로 표시되고 점선으로 나타냅니다." + }, + "images": { + "title": "전체 이미지 모드", + "description": "모든 상의 위치를 표시합니다. 노란색 점은 실상, 주황색 점은 허상, 회색 (예시 그림에는 없음) 점은 가상 객체를 나타냅니다. '광선 밀도'가 충분히 높지 않으면 일부 이미지를 감지할 수 없습니다.", + "simulateColorsNote": "'색상 (파장) 시뮬레이션'이 켜져 있으면 원본 색상으로 표시되고 점 크기로 구분합니다." + }, + "observer": { + "title": "관측자가 보는 이미지 모드", + "description": "특정 위치에서 보는 광선과 상을 시뮬레이션합니다. 파란색 원은 관찰자이며 이것을 지나는 광선은 '관찰된 것'으로 간주됩니다. '관찰된 광선'으로부터 관찰자는 광선이 어디에선가 시작되었다고 생각할 수는 있지만, 실제로 어느 위치에서 시작된 광선인지는 알 수 없습니다. 광선들은 파란색으로, 실상과 허상은 각각 노란색과 주황색 점으로 나타납니다.", + "simulateColorsNote": "'색상 (파장) 시뮬레이션'이 켜져 있으면 원본 색상으로 표시됩니다.", + "instruction": "관찰자의 위치를 옮기려면 큰 파란 점을 드래그하십시오." + } + }, + "simulateColors": { + "title": "색상 (파장) 시뮬레이션", + "description": "광원의 색상 (파장), 색상 혼합, 차단기와 거울에 의한 파장 필터링, 매질의 색 분산을 시뮬레이션합니다.", + "instruction": "개체를 선택할 때 이러한 변수를 설정할 수 있습니다. 색상 스펙트럼을 시뮬레이션 하려면 여러 파장의 광선을 겹치십시오.", + "warning": "화면에 표시되는 색상은 대략적인 근사이며, 광선 밀도가 너무 높거나 낮을 시 매우 부정확할 수 있습니다." + }, + "languageDropdown": { + "title": "언어: {{language}}", + "translatedFraction": "{{fraction}} 번역 됨" + } +} \ No newline at end of file diff --git a/locales/ko/simulator.json b/locales/ko/simulator.json new file mode 100644 index 00000000..c2260c69 --- /dev/null +++ b/locales/ko/simulator.json @@ -0,0 +1,142 @@ +{ + "welcome": { + "title": "광선 광학 시뮬레이션에 오신 것을 환영합니다.", + "instruction": "광학 요소를 추가하려면 도구를 선택한 후 빈 공간을 클릭하십시오.\n예제를 불러오려면 [ 갤러리 페이지](/gallery)로 이동하십시오." + }, + "common": { + "saveButton": "저장", + "cancelButton": "취소", + "closeButton": "닫기" + }, + "file": { + "title": "파일", + "undo": { + "title": "실행 취소" + }, + "redo": { + "title": "재실행" + }, + "reset": { + "title": "재설정" + }, + "save": { + "title": "저장" + }, + "open": { + "title": "열기", + "description": "기존 파일이나 배경 이미지 열기. 배경 이미지는 좌표 원점을 기준으로 표시됩니다. (또는 파일을 올려놓으십시오.)" + }, + "viewGallery": { + "title": "갤러리 보기", + "description": "예제를 불러오기 위해 갤러리로 이동." + } + }, + "settings": { + "title": "설정", + "more": "더 보기", + "rayDensity": { + "title": "광선 밀도", + "description": "빔이나 점광원으로부터 발생하는 광선의 개수를 결정합니다. 상 검출과 색 표현에도 영향을 미칩니다." + }, + "layoutAids": { + "title": "레이아웃 도구", + "showGrid": "격자", + "snapToGrid": "격자선에 물리기", + "lockObjs": "사물 고정" + }, + "zoom": { + "title": "확대/축소" + }, + "language": { + "title": "언어" + }, + "showHelpPopups": { + "title": "도움말 팝업 표시", + "description": "버튼 위를 지날 때 도움말을 표시할 지 결정합니다. (효과 반영을 위해 페이지를 다시 불러옵니다.)" + }, + "advancedHelp": "추가적인 설명이 필요한 경우 우측 하단의 도움말 아이콘을 클릭하십시오." + }, + "objBar": { + "showAdvanced": { + "title": "추가 옵션" + }, + "applyToAll": { + "title": "전체에 적용" + }, + "duplicate": { + "title": "복제" + }, + "delete": { + "title": "삭제" + }, + "unselect": { + "title": "선택 해제", + "description": "이 물체의 선택을 해제합니다. (또는 빈 영역에 우클릭합니다.)" + } + }, + "sceneObjs": { + "common": { + "brightness": "밝기", + "brightnessInfo": { + "rayDensity": "'광선 밀도'가 충분히 높을 때 유효합니다.", + "rayDensitySlider": "방출되는 광선의 개수를 조절하려면 '광선 밀도' 슬라이더를 조절하십시오." + }, + "wavelength": "파장", + "emisAngle": "방출 각", + "random": "랜덤", + "lambert": "램버시안 (Lambertian)", + "focalLength": "초점 거리" + }, + "Beam": { + "imageDetectionWarning": "발산하거나 랜덤한 빔의 경우 정상적으로 인식되지 않거나 작동하지 않을 수 있습니다." + }, + "AngleSource": { + "symmetric": "대칭" + }, + "BaseFilter": { + "filter": "필터", + "bandwidth": "대역폭 (Bandwidth)", + "invert": "반전" + }, + "IdealMirror": { + "cartesianSign": "직교좌표계 부호 변환" + }, + "BeamSplitter": { + "transRatio": "전송률" + }, + "BaseGlass": { + "refIndex": "굴절률", + "refIndexInfo": { + "relative": "다른 매질 내부에 있다면 상대 굴절률", + "effective": "이 객체가 (절대) 굴절률 n₁으로 시뮬레이션되어야 하는데 굴절률이 n₀인 다른 매질 내부에 있다면 상대 굴절률인 n₁/n₀ 를 입력해야합니다. 여러 장의 매질이 겹쳐진 복잡한 경우에는 겹친 영역의 실질적인 굴절률 (effective refractive index)은 매질 각각의 굴절률의 곱과 같습니다." + }, + "cauchyCoeff": "코시 계수 (Cauchy coefficient)" + }, + "TextLabel": { + "fontSize": "폰트 크기", + "font": "폰트", + "fontStyle": "스타일", + "alignment": "정렬", + "smallCaps": "Small Caps", + "angle": "각도" + }, + "CropBox": { + "svgWarning": "SVG로 추출하기. 색상 혼합 및 1 미만의 상대 굴절율은 지원되지 않습니다." + } + }, + "saveModal": { + "title": "저장", + "fileName": "이름" + }, + "languageModal": { + "title": "언어", + "translatedFraction": "번역 됨", + "helpTranslate": "이 앱의 번역 참여" + }, + "generalWarnings": { + "shareLinkTooLong": "URL이 너무 길어서 일부 플랫폼에서 작동하지 않을 수 있습니다. 이 경우 \"저장\"을 사용해 파일을 공유하십시오." + }, + "footer": { + "processing": "작업중... 중단하려면 클릭." + } +} \ No newline at end of file diff --git a/locales/nl.json b/locales/nl.json deleted file mode 100644 index 76f5505b..00000000 --- a/locales/nl.json +++ /dev/null @@ -1,1060 +0,0 @@ -{ - "appName": { - "message": "Ray Optics Simulatie" - }, - "appShortName": { - "incomplete": true, - "message": "Ray Optics" - }, - "appDesc": { - "incomplete": true, - "message": "A free, open-source web app for creating and simulating 2D geometric optical scenes." - }, - "homepage_desc": { - "incomplete": true, - "message": "Create & simulate 2D geometric optical scenes interactively.
Totally free and web-based. Source code is available on GitHub." - }, - "launch_simulator": { - "incomplete": true, - "message": "Launch Simulator" - }, - "home": { - "incomplete": true, - "message": "Home" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/nl/" - }, - "gallery": { - "incomplete": true, - "message": "Gallery" - }, - "gallery_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
To add an optical component, select a tool and click the blank space.
To load an example, please go to the Gallery page." - }, - "loading_msg": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
Loading scene from URL... Please wait." - }, - "toolbar_title": { - "incomplete": true, - "message": "Tool: " - }, - "toolname_SingleRay": { - "message": "Enkele straal" - }, - "toolname_AngleSource": { - "message": "Punt bron" - }, - "toolname_PointSource": { - "message": "Punt bron" - }, - "toolname_Beam": { - "message": "Bundel" - }, - "toolname_mirror_": { - "message": "Spiegel" - }, - "toolname_Mirror": { - "message": "Spiegel" - }, - "toolname_ArcMirror": { - "message": "Spiegel" - }, - "toolname_ParabolicMirror": { - "message": "Spiegel" - }, - "toolname_CustomMirror": { - "incomplete": true, - "message": "Mirror" - }, - "toolname_IdealMirror": { - "message": "Ideale gebogen spiegel" - }, - "toolname_glass_": { - "message": "Glas" - }, - "toolname_blocker_": { - "incomplete": true, - "message": "Blocker" - }, - "toolname_BeamSplitter": { - "incomplete": true, - "message": "Beam Splitter" - }, - "toolname_PlaneGlass": { - "message": "Glas" - }, - "toolname_CircleGlass": { - "message": "Glas" - }, - "toolname_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_Glass": { - "message": "Glas" - }, - "toolname_GrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_IdealLens": { - "message": "Ideale lens" - }, - "toolname_SphericalLens": { - "incomplete": true, - "message": "Spherical lens" - }, - "toolname_CustomGlass": { - "incomplete": true, - "message": "Glass" - }, - "toolname_Blocker": { - "incomplete": true, - "message": "Line Blocker" - }, - "toolname_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "toolname_CircleBlocker": { - "incomplete": true, - "message": "Circle Blocker" - }, - "toolname_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "toolname_Ruler": { - "message": "Lineaal" - }, - "toolname_Protractor": { - "message": "Gradenboog" - }, - "tool_Detector": { - "incomplete": true, - "message": "Detector" - }, - "toolname_Detector": { - "incomplete": true, - "message": "Detector" - }, - "toolname_TextLabel": { - "incomplete": true, - "message": "Text" - }, - "toolname_LineArrow": { - "incomplete": true, - "message": "Line" - }, - "toolname_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "toolname_Handle": { - "incomplete": true, - "message": "Handle" - }, - "toolname_CropBox": { - "incomplete": true, - "message": "Export" - }, - "toolname_ModuleObj": { - "incomplete": true, - "message": "ModuleBeta" - }, - "tool_more_": { - "message": "Overig" - }, - "toolname_": { - "message": "Verplaats beeld" - }, - "modebar_title": { - "message": "Beeld:" - }, - "modename_light": { - "message": "Stralen" - }, - "modename_extended_light": { - "message": "Virtuele stralen" - }, - "modename_images": { - "message": "Alle beelden" - }, - "modename_observer": { - "message": "Zichtbaar voor waarnemer" - }, - "simulateColors": { - "incomplete": true, - "message": "Simulate Colors" - }, - "File: ": { - "message": "Bestand" - }, - "Tools: ": { - "message": "Gereedschap" - }, - "tool_SingleRay": { - "message": "Straal" - }, - "tool_Beam": { - "message": "Bundel" - }, - "tool_PointSource": { - "message": "Punt bron (360°)" - }, - "tool_AngleSource": { - "message": "Punt bron (<360°)" - }, - "tool_PointSource_": { - "message": "Punt bron" - }, - "tool_lightSource_": { - "message": "Lichtbron" - }, - "tool_mirror_": { - "message": "spiegels" - }, - "tool_Mirror": { - "message": "Lijnstuk" - }, - "tool_ArcMirror": { - "message": "Cirkelboog" - }, - "tool_ParabolicMirror": { - "incomplete": true, - "message": "Parabolic" - }, - "tool_CustomMirror": { - "incomplete": true, - "message": "Custom Equation" - }, - "tool_BeamSplitter": { - "incomplete": true, - "message": "Beam Splitter" - }, - "tool_IdealMirror": { - "message": "Ideaal gebogen" - }, - "tool_glass_": { - "message": "Glas" - }, - "tool_blocker_": { - "message": "Scherm" - }, - "tool_PlaneGlass": { - "message": "Halve vlak" - }, - "tool_CircleGlass": { - "message": "Cirkel" - }, - "tool_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index circle" - }, - "tool_Glass": { - "incomplete": true, - "message": "Polygon / Circular Arcs" - }, - "tool_GrinGlass": { - "incomplete": true, - "message": "Gradient-index polygon" - }, - "tool_IdealLens": { - "message": "Ideale Lens" - }, - "tool_SphericalLens": { - "incomplete": true, - "message": "Spherical Lens" - }, - "tool_CustomGlass": { - "incomplete": true, - "message": "Custom Equation" - }, - "tool_Blocker": { - "incomplete": true, - "message": "Line Blocker" - }, - "tool_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "tool_CircleBlocker": { - "incomplete": true, - "message": "Circle Blocker" - }, - "tool_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "tool_Ruler": { - "message": "Lineaal" - }, - "tool_Protractor": { - "message": "Gradenboog" - }, - "tool_TextLabel": { - "incomplete": true, - "message": "Text" - }, - "tool_LineArrow": { - "incomplete": true, - "message": "Line / Arrow" - }, - "tool_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "tool_": { - "message": "Verplaats beeld" - }, - "View: ": { - "message": "Beeld" - }, - "Settings: ": { - "message": "Instellingen" - }, - "moresettings": { - "incomplete": true, - "message": "More" - }, - "mode_rays": { - "message": "Stralen" - }, - "mode_extended": { - "message": "Virtuele stralen" - }, - "mode_images": { - "message": "Alle beelden" - }, - "mode_observer": { - "message": "Beeld voor waarnemer" - }, - "zoom": { - "incomplete": true, - "message": "Zoom" - }, - "help": { - "message": "Help" - }, - "rayDensity": { - "message": "Straaldichtheid" - }, - "raydensity": { - "message": "Straaldichtheid:" - }, - "undo": { - "incomplete": true, - "message": "Undo" - }, - "redo": { - "incomplete": true, - "message": "Redo" - }, - "reset": { - "incomplete": true, - "message": "Reset" - }, - "save": { - "incomplete": true, - "message": "Save" - }, - "rename": { - "incomplete": true, - "message": "Rename" - }, - "get_link": { - "incomplete": true, - "message": "Copy Shareable Link" - }, - "export_svg": { - "incomplete": true, - "message": "Export as PNG/SVG" - }, - "view_gallery": { - "incomplete": true, - "message": "View Gallery" - }, - "save_name": { - "message": "Naam" - }, - "save_cancel": { - "incomplete": true, - "message": "Cancel" - }, - "save_description": { - "incomplete": true, - "message": "" - }, - "open": { - "incomplete": true, - "message": "Open" - }, - "layoutaids": { - "incomplete": true, - "message": "Layout Aids" - }, - "lockObjs": { - "incomplete": true, - "message": "Lock Objects" - }, - "showGrid": { - "incomplete": true, - "message": "Grid" - }, - "snapToGrid": { - "incomplete": true, - "message": "Snap to Grid" - }, - "snaptogrid": { - "incomplete": true, - "message": "Snap to Grid" - }, - "length_unit_popover": { - "incomplete": true, - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "incomplete": true, - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "incomplete": true, - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "message": "Helderheid" - }, - "wavelength": { - "message": "Golflengte (nm)" - }, - "dichroic": { - "message": "Dichroïde" - }, - "filter": { - "message": "Filter" - }, - "bandwidth": { - "message": "Bandbreedte (nm)" - }, - "invert": { - "message": "Omkeren" - }, - "emisAngle": { - "incomplete": true, - "message": "Emission Angle (°)" - }, - "mirrored": { - "incomplete": true, - "message": "Mirrored" - }, - "lineDensity": { - "incomplete": true, - "message": "Lines/mm" - }, - "slitRatio": { - "incomplete": true, - "message": "Slit width / line spacing" - }, - "customBrightness": { - "incomplete": true, - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "incomplete": true, - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "incomplete": true, - "message": "Symmetric" - }, - "eqn_note": { - "incomplete": true, - "message": "" - }, - "symbolic_grin": { - "incomplete": true, - "message": "Symbolic body-merging" - }, - "grin_refractive_index": { - "incomplete": true, - "message": "" - }, - "symbolic_grin_note_popover": { - "incomplete": true, - "message": "

This toggle applies to all GRIN objects in the simulation.

This simulator has currently two implementations of light propagation between different mediums, for GRIN objects - numerical and symbolic (see 'multRefIndex' and 'devRefIndex' functions in 'CircleGrinGlass.js').

The numerical implementation is faster but doesn't always work properly (depending on the specific case) in scenarios when used with more than one GRIN object, such that at least one of them has a refractive index function which is not defined in the entire plane, while the symbolic implementation is slower but robust to such problems.

" - }, - "focalLength": { - "message": "Brandpuntafstand" - }, - "cartesianSign": { - "incomplete": true, - "message": "Cartesian Sign Convention" - }, - "refIndex": { - "message": "Brekingsindex*" - }, - "radii_of_curvature": { - "incomplete": true, - "message": "Radii of Curvature" - }, - "focal_distances": { - "incomplete": true, - "message": "Focal Distances" - }, - "refIndex_origin": { - "incomplete": true, - "message": "Origin of n(x,y)" - }, - "stepSize": { - "incomplete": true, - "message": "Numerical solver step size" - }, - "intersectTol": { - "incomplete": true, - "message": "Intersection tolerance" - }, - "random": { - "incomplete": true, - "message": "Random" - }, - "lambert": { - "incomplete": true, - "message": "Lambertian" - }, - "diameter": { - "incomplete": true, - "message": "Diameter" - }, - "irradMap": { - "incomplete": true, - "message": "Irradiance Map" - }, - "binSize": { - "incomplete": true, - "message": "Bin Size" - }, - "scaleInterval": { - "incomplete": true, - "message": "Scale interval" - }, - "exportData": { - "incomplete": true, - "message": "Export data" - }, - "demodulize": { - "incomplete": true, - "message": "Demodulize" - }, - "fontSize": { - "incomplete": true, - "message": "Font Size" - }, - "font": { - "incomplete": true, - "message": "Font" - }, - "fontStyle": { - "incomplete": true, - "message": "Style" - }, - "normal": { - "incomplete": true, - "message": "Normal" - }, - "bold": { - "incomplete": true, - "message": "Bold" - }, - "italic": { - "incomplete": true, - "message": "Italic" - }, - "bolditalic": { - "incomplete": true, - "message": "Bold Italic" - }, - "oblique": { - "incomplete": true, - "message": "Oblique" - }, - "boldoblique": { - "incomplete": true, - "message": "Bold Oblique" - }, - "alignment": { - "incomplete": true, - "message": "Alignment" - }, - "left": { - "incomplete": true, - "message": "Left" - }, - "center": { - "incomplete": true, - "message": "Centre" - }, - "right": { - "incomplete": true, - "message": "Right" - }, - "text_here": { - "incomplete": true, - "message": "Text Here" - }, - "smallCaps": { - "incomplete": true, - "message": "Small Caps" - }, - "angle": { - "incomplete": true, - "message": "Angle (°)" - }, - "arrow": { - "incomplete": true, - "message": "Forward arrow" - }, - "backArrow": { - "incomplete": true, - "message": "Backward arrow" - }, - "stop_drawing": { - "incomplete": true, - "message": "Finish Drawing" - }, - "cropBoxSize": { - "incomplete": true, - "message": "Crop Box Size" - }, - "format": { - "incomplete": true, - "message": "Format" - }, - "width": { - "incomplete": true, - "message": "Width" - }, - "rayCountLimit": { - "incomplete": true, - "message": "Ray count limit" - }, - "transformation": { - "incomplete": true, - "message": "TransformationBeta" - }, - "default": { - "incomplete": true, - "message": "Default" - }, - "translation": { - "incomplete": true, - "message": "Translation" - }, - "xTranslation": { - "incomplete": true, - "message": "X Translation" - }, - "yTranslation": { - "incomplete": true, - "message": "Y Translation" - }, - "rotation": { - "incomplete": true, - "message": "Rotation" - }, - "scaling": { - "incomplete": true, - "message": "Scaling" - }, - "beam_warning": { - "incomplete": true, - "message": "Image detection may not work with divergent/random beams." - }, - "image_detection_warning": { - "incomplete": true, - "message": "This tool does not support image detection." - }, - "non_simulateColors_warning": { - "incomplete": true, - "message": "This tool only works when \"Simulate Color\" is on." - }, - "brightness_note_popover": { - "incomplete": true, - "message": "

Only effective if 'Ray Density' is high enough.

To control the numbers of rays emitted, please adjust the global 'Ray Density' slider instead.

" - }, - "refIndex_note_popover": { - "incomplete": true, - "message": "

*Relative if inside another glass

If this object is to be simulated with (absolute) refractive index n₁, but is placed inside another glass with refractive index n₀, then you should set the refractive index to n₁/n₀ here. In more complicated cases that several glasses overlap together, the effective reflective index of the overlapping region equals the product of the reflective indices of individual ones.

" - }, - "stepSize_note_popover": { - "incomplete": true, - "message": "

Step size of Euler's method for solving the eikonal ray equation - see 'step' function and documentation inside the 'CircleGrinGlass.js' file, for more information.

" - }, - "eps_CircleGrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length]^2.

This numerical tolerance is used in the functions 'isOutsideGlass', 'isInsideGlass' and 'isOnBoundary', inside the 'CircleGrinGlass.js' file.

" - }, - "eps_GrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length].

This numerical tolerance is used in the functions 'isOnBoundary' and 'countIntersections', inside the 'GrinGlass.js' file.

" - }, - "cauchyCoeff": { - "incomplete": true, - "message": "Cauchy coefficient" - }, - "transRatio": { - "incomplete": true, - "message": "Transmission Ratio" - }, - "applytoall": { - "message": "Overal toepassen" - }, - "duplicate": { - "message": "Dupliceer" - }, - "delete": { - "message": "Verwijder" - }, - "unselect": { - "incomplete": true, - "message": "Unselect" - }, - "unselect_popover": { - "incomplete": true, - "message": "Unselect this object (Right-click on blank space has the same function.)" - }, - "showadvanced": { - "incomplete": true, - "message": "More options..." - }, - "processing": { - "message": "Rekenen... Klik hier om te stoppen." - }, - "contribute": { - "incomplete": true, - "message": "Contribute" - }, - "github": { - "incomplete": true, - "message": "GitHub" - }, - "about": { - "incomplete": true, - "message": "About" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "incomplete": true, - "message": "Help us translate this app" - }, - "translated": { - "incomplete": true, - "message": "translated" - }, - "undo_popover": { - "message": "Laatste actie ongedaan maken. (Ctrl+Z)" - }, - "redo_popover": { - "message": "Laatste actie opnieuw. (Ctrl+Y)" - }, - "reset_popover": { - "message": "Alle wijzigingen ongedaan maken." - }, - "save_popover": { - "message": "Huidig bestand opslaan." - }, - "open_popover": { - "incomplete": true, - "message": "Open an existing file or background image. The background image will be shown from the coordinate origin. (Or drop the file)" - }, - "get_link_popover": { - "incomplete": true, - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "incomplete": true, - "message": "The URL is too long that it may not work on some platforms. You may need to use \"Save\" and share the file instead." - }, - "export_svg_warning": { - "incomplete": true, - "message": "Export to SVG: Color mixtures and relative refractive indices below 1 are not supported." - }, - "export_ray_count_warning": { - "incomplete": true, - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "incomplete": true, - "message": "Go to the Gallery webpage to load an example." - }, - "tool_SingleRay_popover": { - "message": "Één straal door twee punten. (Sleep of klik om te maken. Eerste punt is de bron. Tweede punt geeft de richting.)" - }, - "tool_Beam_popover": { - "incomplete": true, - "message": "A parallel or divergent beam of rays emerges from a line segment, with density controlled by the 'Ray density' slider. (Drag or click to create.)" - }, - "tool_PointSource_popover": { - "message": "Lichtstralen vanuit één punt, het aantal stralen wordt ingesteld met 'Straaldichtheid'. (Klik om te maken.)" - }, - "tool_AngleSource_popover": { - "incomplete": true, - "message": "Point source with a given emission angle." - }, - "tool_Mirror_popover": { - "message": "Simuleert de reflectie van licht op een spiegel. (Sleep of klik om te maken.)" - }, - "tool_ArcMirror_popover": { - "message": "Een spiegel in de vorm van een cirkelboog, door drie punten vastgelegd. De eerste twee punten leggen de afstand tussen de randen vast, het laatste punt de grootte.)" - }, - "tool_ParabolicMirror_popover": { - "incomplete": true, - "message": "A mirror whose shape is a parabola, which is defined by three points. (Drag or click to create.)" - }, - "tool_CustomMirror_popover": { - "incomplete": true, - "message": "A mirror whose shape is defined by a custom equation y = f(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0). (Drag or click to create.)" - }, - "tool_BeamSplitter_popover": { - "incomplete": true, - "message": "A mirror that transmits a percentage of incoming light. (Drag or click to create.)" - }, - "tool_IdealMirror_popover": { - "message": "Een ideale 'gebogen' spiegel die precies de spiegel formule volgt (1/p + 1/q = 1/f). De brandpuntsafstand kan worden ingevoerd. (Sleep of klik om te maken.)" - }, - "tool_PlaneGlass_popover": { - "message": "Simuleert de refractie en reflectie van licht op/door een oppervlak. (Sleep of klik om te maken.)" - }, - "tool_CircleGlass_popover": { - "message": "Glasschijf, gedefinieerd door middelpunt en een punt op de rand. (Sleep of klik om te maken.)" - }, - "tool_CircleGrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a circular boundary. (Drag or click to create.)" - }, - "tool_Glass_popover": { - "message": "Glas in willekeurige vorm uit lijnstukken en cirkelbogen. (Klik om een lijnstuk te maken, sleep om een cirkelboog te maken, klik op startpunt om tekenen te sluiten.)" - }, - "tool_GrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a polygonal boundary. WARNING: Only simple polygons are supported, otherwise the behavior is unpredictable. (Click to create a segment, click on the starting point when finish drawing.)" - }, - "tool_IdealLens_popover": { - "message": "Een ideale lens die de lenzenformule volgt (1/v + 1/b = 1/f). De brandpuntafstand kan worden ingevoerd. (Sleep of klik om te maken.)" - }, - "tool_SphericalLens_popover": { - "incomplete": true, - "message": "A spherical lens. (Click to create.)" - }, - "tool_CustomGlass_popover": { - "incomplete": true, - "message": "Glass with the shape defined by a custom inequality f(x) < y < g(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0). (Drag or click to create.)" - }, - "tool_Blocker_popover": { - "message": "Een lichtblokkerend lijnstuk (scherm). (Sleep of klik om te maken.)" - }, - "tool_Aperture_popover": { - "incomplete": true, - "message": "A pair of light blockers which absorbs the incident rays. The size of the hole can be adjusted symmetrically. (Drag or click the two endpoints to create.)" - }, - "tool_CircleBlocker_popover": { - "incomplete": true, - "message": "A circle light blocker which absorbs the incident rays. (Drag or click to create.)" - }, - "tool_DiffractionGrating_popover": { - "incomplete": true, - "message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)" - }, - "tool_Ruler_popover": { - "message": "Een lineaal van 0 tot een willekeurige afstand. (Sleep of klik om te maken.)" - }, - "tool_Protractor_popover": { - "message": "Een gradenboog van middelpunt tot een ander punt (hoek 0). De schaal is in graden. (Sleep of klik om te maken.)" - }, - "tool_Detector_popover": { - "incomplete": true, - "message": "A tool for measuring the rate of energy flow (P), the rate of perpendicular momentum flow (F⊥), and the rate of parallel momentum flow (F∥) through a line segment. (Drag or click to create the line segment.) The units are arbitrary." - }, - "tool_Detector_info_popover": { - "incomplete": true, - "message": "" - }, - "tool_TextLabel_popover": { - "incomplete": true, - "message": "A text label." - }, - "tool_LineArrow_popover": { - "incomplete": true, - "message": "A line segment or arrow. (Drag or click to create.)" - }, - "tool_Drawing_popover": { - "incomplete": true, - "message": "A freehand drawing tool. (Drag to draw.)" - }, - "tool__popover": { - "message": "Sleep om beeld te verplaatsen. (Rechtermuisknop sleep heeft dezelfde functie.)" - }, - "mode_rays_popover": { - "message": "Toont de stralen. Als de 'Straaldichtheid' groot is lijkt het continu." - }, - "mode_extended_popover": { - "incomplete": true, - "message": "Show both the rays and its extension. Orange indicates backward extensions, and gray indicates forward ones.
When 'Simulate Colors' is on, they are shown in source colors and distinguished by dashing instead." - }, - "mode_images_popover": { - "incomplete": true, - "message": "Show the position of all images. Yellow points indicate real images, orange indicates virtual images, and gray (none in this picture) indicates virtual objects. Note that some images cannot be detected if 'Ray density' is not high enough.
When 'Simulate Colors' is on, they are shown in source colors and distinguished by dot sizes instead." - }, - "mode_observer_popover": { - "incomplete": true, - "message": "Simulate the rays and images seen from some position. The blue circle is the observer. Any rays crossing it are considered to be 'observed'. The observer does not know where the rays actually begin, but may think they begin at some point(s) if they intersect there. The rays are shown in blue, and the points in yellow (real) or orange (virtual). (Drag the big blue dot to move the observer.)
When 'Simulate Colors' is on, they are shown in source colors instead." - }, - "simulateColors_popover": { - "incomplete": true, - "message": "Simulate colors (wavelengths) of light sources, mixture of colors, color filtering of blockers and mirrors, and chromatic dispersion of glasses. You can set those parameters for those objects when selected. To simulate color spectra, overlap rays with different wavelengths. The colors shown on the screen are only rough approximations, and can be very inaccurate when 'Ray density' is too high or too low." - }, - "rayDensity_popover": { - "incomplete": true, - "message": "Determines the number of rays to be emitted by beams and point sources. This also affects the accuracy of image detection and color rendering." - }, - "showGrid_popover": { - "message": "Toont of verbergt het achtergrondraster." - }, - "grid_popover": { - "message": "Zet verplaatsen op raster aan of uit." - }, - "lockObjs_popover": { - "message": "(De)Blokkeert de verplaatsing van objecten." - }, - "zoom_popover": { - "message": "Beeld in/uitzoomen met een percentage." - }, - "help_popover": { - "incomplete": true, - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "incomplete": true, - "message": "Show help popups" - }, - "show_help_popups_popover": { - "incomplete": true, - "message": "Defines whether to show help popups when hovering over buttons. (Reload the page to take effect.)" - }, - "show_json_editor": { - "incomplete": true, - "message": "Show JSON editorBeta" - }, - "show_json_editor_popover": { - "incomplete": true, - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "incomplete": true, - "message": "Show status box" - }, - "show_status_popover": { - "incomplete": true, - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "incomplete": true, - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "incomplete": true, - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "incomplete": true, - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "incomplete": true, - "message": "Grid Size" - }, - "observer_size": { - "incomplete": true, - "message": "Observer Size" - }, - "language": { - "incomplete": true, - "message": "Language" - }, - "close": { - "incomplete": true, - "message": "Close" - }, - "advanced_help": { - "incomplete": true, - "message": "For advanced help, see the help icon in the lower-right corner." - }, - "ray_count": { - "incomplete": true, - "message": "Number of ray segments: " - }, - "total_truncation": { - "incomplete": true, - "message": "Truncated brightness: " - }, - "brightness_scale": { - "incomplete": true, - "message": "Brightness Scale: " - }, - "time_elapsed": { - "incomplete": true, - "message": "Time elapsed (ms): " - }, - "force_stopped": { - "incomplete": true, - "message": "Force stopped." - }, - "mouse_coordinates": { - "incomplete": true, - "message": "Mouse coordinates: " - }, - "modules_tutorial": { - "incomplete": true, - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "incomplete": true, - "message": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior." - }, - "import_modules": { - "incomplete": true, - "message": "Import Modules..." - }, - "import_modules_title": { - "incomplete": true, - "message": "Import Modules" - }, - "modules_url": { - "incomplete": true, - "message": "../modules/modules.html" - }, - "remove_module": { - "incomplete": true, - "message": "Remove module" - }, - "module_conflict": { - "incomplete": true, - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "incomplete": true, - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/nl/main.json b/locales/nl/main.json new file mode 100644 index 00000000..444ea2b0 --- /dev/null +++ b/locales/nl/main.json @@ -0,0 +1,118 @@ +{ + "meta": { + "languageName": "Nederlands", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "Ray Optics Simulatie" + }, + "homePage": { + "description": "Een open-source web applicatie om reflectie en refractie van licht te simuleren.\nGeschreven in HTML, CSS en JavaScript. ([GitHub](/github))", + "launchSimulator": "Start Applicatie" + }, + "tools": { + "title": "Gereedschap", + "categories": { + "lightSource": "Lichtbron", + "mirror": "spiegels", + "glass": "Glas", + "blocker": "Scherm", + "other": "Overig" + }, + "common": { + "clickInstruction": "Klik om te maken.", + "lineInstruction": "Sleep of klik om te maken.", + "circleInstruction": "Sleep of klik om te maken." + }, + "SingleRay": { + "title": "Straal", + "description": "Één straal door twee punten.", + "instruction": "Sleep of klik om te maken. Eerste punt is de bron. Tweede punt geeft de richting." + }, + "Beam": { + "title": "Bundel", + "description": "Een evenwijdige bundel uit een lijnstuk, het aantal stralen wordt ingesteld met 'Straaldichtheid'. (Also supports divergent beams.)" + }, + "PointSource": { + "title": "Punt bron", + "description": "Lichtstralen vanuit één punt, het aantal stralen wordt ingesteld met 'Straaldichtheid'." + }, + "AngleSource": { + "instruction": "Sleep of klik om te maken. Eerste punt is de bron. Tweede punt geeft de richting." + }, + "Mirror": { + "title": "Lijnstuk", + "description": "Simuleert de reflectie van licht op een spiegel." + }, + "otherMirror": { + "title": "Cirkelboog", + "description": "Een spiegel in de vorm van een cirkelboog, door drie punten vastgelegd." + }, + "ArcMirror": { + "title": "Cirkelboog", + "description": "Een spiegel in de vorm van een cirkelboog, door drie punten vastgelegd.", + "instruction": "De eerste twee punten leggen de afstand tussen de randen vast, het laatste punt de grootte." + }, + "IdealMirror": { + "title": "Ideaal gebogen", + "description": "Een ideale 'gebogen' spiegel die precies de spiegel formule volgt (1/p + 1/q = 1/f). De brandpuntsafstand kan worden ingevoerd." + }, + "PlaneGlass": { + "title": "Halve vlak", + "description": "Simuleert de refractie en reflectie van licht op/door een oppervlak.", + "instruction": "Sleep of klik om te maken." + }, + "otherGlass": { + "title": "Overig", + "description": "Glas in willekeurige vorm uit lijnstukken en cirkelbogen." + }, + "CircleGlass": { + "title": "Cirkel", + "description": "Glasschijf, gedefinieerd door middelpunt en een punt op de rand." + }, + "Glass": { + "description": "Glas in willekeurige vorm uit lijnstukken en cirkelbogen.", + "instruction": "Klik om een lijnstuk te maken, sleep om een cirkelboog te maken, klik op startpunt om tekenen te sluiten." + }, + "IdealLens": { + "title": "Ideale Lens", + "description": "Een ideale lens die de lenzenformule volgt (1/v + 1/b = 1/f). De brandpuntafstand kan worden ingevoerd." + }, + "Blocker": { + "description": "Een lichtblokkerend lijnstuk (scherm)." + }, + "Ruler": { + "title": "Lineaal", + "description": "Een lineaal van 0 tot een willekeurige afstand." + }, + "Protractor": { + "title": "Gradenboog", + "description": "Een gradenboog van middelpunt tot een ander punt (hoek 0). De schaal is in graden." + }, + "moveView": { + "title": "Verplaats beeld", + "description": "Sleep om beeld te verplaatsen. (Rechtermuisknop sleep heeft dezelfde functie.)" + } + }, + "view": { + "title": "Beeld", + "rays": { + "title": "Stralen", + "description": "Toont de stralen. Als de 'Straaldichtheid' groot is lijkt het continu." + }, + "extended": { + "title": "Virtuele stralen" + }, + "images": { + "title": "Alle beelden" + }, + "observer": { + "title": "Beeld voor waarnemer" + } + }, + "languageDropdown": { + "title": "Taal: {{language}}" + } +} \ No newline at end of file diff --git a/locales/nl/simulator.json b/locales/nl/simulator.json new file mode 100644 index 00000000..25548713 --- /dev/null +++ b/locales/nl/simulator.json @@ -0,0 +1,49 @@ +{ + "file": { + "title": "Bestand" + }, + "settings": { + "title": "Instellingen", + "rayDensity": { + "title": "Straaldichtheid" + }, + "language": { + "title": "Taal" + } + }, + "objBar": { + "applyToAll": { + "title": "Overal toepassen" + }, + "duplicate": { + "title": "Dupliceer" + }, + "delete": { + "title": "Verwijder" + } + }, + "sceneObjs": { + "common": { + "brightness": "Helderheid", + "wavelength": "Golflengte", + "focalLength": "Brandpuntafstand" + }, + "BaseFilter": { + "filter": "Filter", + "bandwidth": "Bandbreedte", + "invert": "Omkeren" + }, + "BaseGlass": { + "refIndex": "Brekingsindex" + } + }, + "saveModal": { + "fileName": "Naam" + }, + "languageModal": { + "title": "Taal" + }, + "footer": { + "processing": "Rekenen... Klik hier om te stoppen." + } +} \ No newline at end of file diff --git a/locales/pl.json b/locales/pl.json deleted file mode 100644 index 31a18b8c..00000000 --- a/locales/pl.json +++ /dev/null @@ -1,939 +0,0 @@ -{ - "appName": { - "message": "Symulacja biegu promieni" - }, - "appShortName": { - "message": "Optyka geometryczna" - }, - "appDesc": { - "message": "Aplikacja internetowa open source umożliwiająca symulację odbicia i załamania światła." - }, - "homepage_desc": { - "message": "Twórz i symuluj interaktywnie sceny optyki geometrycznej 2D.
Całkowicie darmowa aplikacja webowa. Kod źródłowy jest dostępny na GitHub." - }, - "launch_simulator": { - "message": "Uruchom symulator" - }, - "home": { - "message": "Strona główna" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/pl/" - }, - "gallery": { - "message": "Galeria" - }, - "gallery_url": { - "message": "https://phydemo.app/ray-optics/pl/gallery/" - }, - "welcome": { - "message": "Witamy w symulacji promieni optycznych
Aby dodać komponent optyczny, zaznacz narzędzie i kliknij puste miejsce.
Aby załadować przykład, przejdź do strony Galerii." - }, - "loading_msg": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
Loading scene from URL... Please wait." - }, - "toolbar_title": { - "message": "Narzędzie: " - }, - "toolname_SingleRay": { - "message": "Pojedynczy promień" - }, - "toolname_AngleSource": { - "message": "Źródło punktowe" - }, - "toolname_PointSource": { - "message": "Źródło punktowe" - }, - "toolname_Beam": { - "message": "Wiązka" - }, - "toolname_mirror_": { - "message": "Zwierciadło" - }, - "toolname_Mirror": { - "message": "Zwierciadło" - }, - "toolname_ArcMirror": { - "message": "Zwierciadło" - }, - "toolname_ParabolicMirror": { - "message": "Zwierciadło" - }, - "toolname_CustomMirror": { - "message": "Zakrzywione zwierciadło" - }, - "toolname_IdealMirror": { - "message": "Idealnie zakrzywione zwierciadło" - }, - "toolname_glass_": { - "message": "Szkło" - }, - "toolname_blocker_": { - "message": "Blokada" - }, - "toolname_BeamSplitter": { - "message": "Rozdzielacz wiązki" - }, - "toolname_PlaneGlass": { - "message": "Półpłaszczyzna" - }, - "toolname_CircleGlass": { - "message": "Koło" - }, - "toolname_CircleGrinGlass": { - "message": "Szkło gradientowe (GRIN)" - }, - "toolname_Glass": { - "message": "Soczewki i inne" - }, - "toolname_GrinGlass": { - "message": "Szkło gradientowe (GRIN)" - }, - "toolname_IdealLens": { - "message": "Soczewka idealna" - }, - "toolname_SphericalLens": { - "message": "Soczewka sferyczna" - }, - "toolname_CustomGlass": { - "message": "Szkło" - }, - "toolname_Blocker": { - "message": "Przesłona liniowa" - }, - "toolname_Aperture": { - "message": "Apertura" - }, - "toolname_CircleBlocker": { - "message": "Przesłona kołowa" - }, - "toolname_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "toolname_Ruler": { - "message": "Linijka" - }, - "toolname_Protractor": { - "message": "Kątomierz" - }, - "tool_Detector": { - "message": "Detektor" - }, - "toolname_Detector": { - "message": "Detektor" - }, - "toolname_TextLabel": { - "message": "Tekst" - }, - "toolname_LineArrow": { - "message": "Linia" - }, - "toolname_Drawing": { - "message": "Rysunek" - }, - "toolname_Handle": { - "incomplete": true, - "message": "Handle" - }, - "toolname_CropBox": { - "incomplete": true, - "message": "Export" - }, - "toolname_ModuleObj": { - "incomplete": true, - "message": "ModuleBeta" - }, - "tool_more_": { - "message": "Inne" - }, - "toolname_": { - "message": "Przesuń widok" - }, - "modebar_title": { - "message": "Widok:" - }, - "modename_light": { - "message": "Promienie" - }, - "modename_extended_light": { - "message": "Rozszerzone promienie" - }, - "modename_images": { - "message": "Wszystkie obrazy" - }, - "modename_observer": { - "message": "Widziane przez obserwatora" - }, - "simulateColors": { - "message": "Symuluj kolory" - }, - "File: ": { - "message": "Plik" - }, - "Tools: ": { - "message": "Narzędzia" - }, - "tool_SingleRay": { - "message": "Promień" - }, - "tool_Beam": { - "message": "Wiązka" - }, - "tool_PointSource": { - "message": "Źródło punktowe (360°)" - }, - "tool_AngleSource": { - "message": "Źródło punktowe (<360°)" - }, - "tool_PointSource_": { - "message": "Źródło punktowe" - }, - "tool_lightSource_": { - "message": "Źródło światła" - }, - "tool_mirror_": { - "message": "Zwierciadła" - }, - "tool_Mirror": { - "message": "Płaskie" - }, - "tool_ArcMirror": { - "message": "Sferyczne" - }, - "tool_ParabolicMirror": { - "message": "Paraboliczne" - }, - "tool_CustomMirror": { - "message": "Równanie niestandardowe" - }, - "tool_BeamSplitter": { - "message": "Rozdzielacz wiązki" - }, - "tool_IdealMirror": { - "message": "Idealnie zakrzywione" - }, - "tool_glass_": { - "message": "Szkła" - }, - "tool_blocker_": { - "message": "Przesłony" - }, - "tool_PlaneGlass": { - "message": "Półpłaszczyzna" - }, - "tool_CircleGlass": { - "message": "Koło" - }, - "tool_CircleGrinGlass": { - "message": "Koło gradientowe" - }, - "tool_Glass": { - "message": "Dowolny kształt / Wielokąt" - }, - "tool_GrinGlass": { - "message": "Wielokąt gradientowy" - }, - "tool_IdealLens": { - "message": "Soczewka idealna" - }, - "tool_SphericalLens": { - "message": "Soczewka sferyczna" - }, - "tool_CustomGlass": { - "message": "Równanie niestandardowe" - }, - "tool_Blocker": { - "message": "Przesłona liniowa" - }, - "tool_Aperture": { - "message": "Apertura" - }, - "tool_CircleBlocker": { - "message": "Przesłona kołowa" - }, - "tool_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "tool_Ruler": { - "message": "Linijka" - }, - "tool_Protractor": { - "message": "Kątomierz" - }, - "tool_TextLabel": { - "message": "Tekst" - }, - "tool_LineArrow": { - "message": "Linia / Strzałka" - }, - "tool_Drawing": { - "message": "Rysunek" - }, - "tool_": { - "message": "Przesuń widok" - }, - "View: ": { - "message": "Widok" - }, - "Settings: ": { - "message": "Ustawienia" - }, - "moresettings": { - "message": "Więcej" - }, - "mode_rays": { - "message": "Promienie" - }, - "mode_extended": { - "message": "Rozszerzone promienie" - }, - "mode_images": { - "message": "Wszystkie obrazy" - }, - "mode_observer": { - "message": "Widziane przez obserwatora" - }, - "zoom": { - "message": "Zoom" - }, - "help": { - "message": "Pomoc" - }, - "rayDensity": { - "message": "Gęstość promieni" - }, - "raydensity": { - "message": "Gęstość promieni:" - }, - "undo": { - "message": "Cofnij" - }, - "redo": { - "message": "Ponów" - }, - "reset": { - "message": "Resetuj" - }, - "save": { - "message": "Zapisz" - }, - "rename": { - "incomplete": true, - "message": "Rename" - }, - "get_link": { - "incomplete": true, - "message": "Copy Shareable Link" - }, - "export_svg": { - "incomplete": true, - "message": "Export as PNG/SVG" - }, - "view_gallery": { - "message": "Zobacz Galerię" - }, - "save_name": { - "message": "Nazwa" - }, - "save_cancel": { - "message": "Anuluj" - }, - "save_description": { - "incomplete": true, - "message": "" - }, - "open": { - "message": "Otwórz" - }, - "layoutaids": { - "message": "Opcje układu" - }, - "lockObjs": { - "message": "Zablokuj obiekty" - }, - "showGrid": { - "message": "Siatka" - }, - "snapToGrid": { - "message": "Przyciągaj do siatki" - }, - "snaptogrid": { - "message": "Przyciągaj do siatki" - }, - "length_unit_popover": { - "incomplete": true, - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "incomplete": true, - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "incomplete": true, - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "message": "Jasność" - }, - "wavelength": { - "message": "Długość fali (nm)" - }, - "dichroic": { - "message": "Dichroiczne" - }, - "filter": { - "message": "Filtr" - }, - "bandwidth": { - "message": "Szerokość pasma (nm)" - }, - "invert": { - "message": "Odwróć" - }, - "emisAngle": { - "message": "Kąt emisji (°)" - }, - "mirrored": { - "incomplete": true, - "message": "Mirrored" - }, - "lineDensity": { - "incomplete": true, - "message": "Lines/mm" - }, - "slitRatio": { - "incomplete": true, - "message": "Slit width / line spacing" - }, - "customBrightness": { - "incomplete": true, - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "incomplete": true, - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "message": "Symetryczna" - }, - "eqn_note": { - "incomplete": true, - "message": "" - }, - "symbolic_grin": { - "message": "Symboliczne łączenie ciał" - }, - "grin_refractive_index": { - "incomplete": true, - "message": "" - }, - "symbolic_grin_note_popover": { - "message": "

Ten przełącznik dotyczy wszystkich obiektów GRIN w symulacji.

Ten symulator ma obecnie dwie implementacje propagacji światła między różnymi ośrodkami dla obiektów GRIN - numeryczną i symboliczną (patrz funkcje 'multRefIndex' i 'devRefIndex' w 'CircleGrinGlass.js').

Implementacja numeryczna jest szybsza, ale nie zawsze działa poprawnie (w zależności od konkretnego przypadku) w scenariuszach, gdy jest używana z więcej niż jednym obiektem GRIN, takim, że przynajmniej jeden z nich ma funkcję współczynnika załamania światła, która nie jest zdefiniowana w całej płaszczyźnie, podczas gdy implementacja symboliczna jest wolniejsza, ale odporna na takie problemy.

" - }, - "focalLength": { - "message": "Ogniskowa:" - }, - "cartesianSign": { - "message": "Konwencja znaków" - }, - "refIndex": { - "message": "Współczynnik załamania*" - }, - "radii_of_curvature": { - "incomplete": true, - "message": "Radii of Curvature" - }, - "focal_distances": { - "incomplete": true, - "message": "Focal Distances" - }, - "refIndex_origin": { - "message": "Początek układu n(x,y)" - }, - "stepSize": { - "message": "Rozmiar kroku rozwiązywania numerycznego" - }, - "intersectTol": { - "message": "Tolerancja intersekcji" - }, - "random": { - "message": "Losowo" - }, - "lambert": { - "message": "Lambertowskie" - }, - "diameter": { - "message": "Średnica" - }, - "irradMap": { - "message": "Mapa irradiancji" - }, - "binSize": { - "message": "Rozmiar pojemnika" - }, - "scaleInterval": { - "incomplete": true, - "message": "Scale interval" - }, - "exportData": { - "message": "Eksportuj dane" - }, - "demodulize": { - "incomplete": true, - "message": "Demodulize" - }, - "fontSize": { - "message": "Rozmiar czcionki" - }, - "font": { - "message": "Czcionka" - }, - "fontStyle": { - "message": "Styl" - }, - "normal": { - "incomplete": true, - "message": "Normal" - }, - "bold": { - "incomplete": true, - "message": "Bold" - }, - "italic": { - "incomplete": true, - "message": "Italic" - }, - "bolditalic": { - "incomplete": true, - "message": "Bold Italic" - }, - "oblique": { - "incomplete": true, - "message": "Oblique" - }, - "boldoblique": { - "incomplete": true, - "message": "Bold Oblique" - }, - "alignment": { - "message": "Wyrównanie" - }, - "left": { - "incomplete": true, - "message": "Left" - }, - "center": { - "incomplete": true, - "message": "Centre" - }, - "right": { - "incomplete": true, - "message": "Right" - }, - "text_here": { - "incomplete": true, - "message": "Text Here" - }, - "smallCaps": { - "message": "Małe litery" - }, - "angle": { - "message": "Kąt (°)" - }, - "arrow": { - "message": "Strzałka do przodu" - }, - "backArrow": { - "message": "Strzałka do tyłu" - }, - "stop_drawing": { - "message": "Zakończ rysowanie" - }, - "cropBoxSize": { - "incomplete": true, - "message": "Crop Box Size" - }, - "format": { - "incomplete": true, - "message": "Format" - }, - "width": { - "incomplete": true, - "message": "Width" - }, - "rayCountLimit": { - "incomplete": true, - "message": "Ray count limit" - }, - "transformation": { - "incomplete": true, - "message": "TransformationBeta" - }, - "default": { - "incomplete": true, - "message": "Default" - }, - "translation": { - "incomplete": true, - "message": "Translation" - }, - "xTranslation": { - "incomplete": true, - "message": "X Translation" - }, - "yTranslation": { - "incomplete": true, - "message": "Y Translation" - }, - "rotation": { - "incomplete": true, - "message": "Rotation" - }, - "scaling": { - "incomplete": true, - "message": "Scaling" - }, - "beam_warning": { - "message": "Wykrywanie obrazu może nie działać w przypadku wiązek rozbieżnych/losowych." - }, - "image_detection_warning": { - "incomplete": true, - "message": "This tool does not support image detection." - }, - "non_simulateColors_warning": { - "incomplete": true, - "message": "This tool only works when \"Simulate Color\" is on." - }, - "brightness_note_popover": { - "message": "

Efektywne tylko wtedy, gdy 'Gęstość promieni' jest wystarczająco wysoka.

Aby kontrolować liczbę emitowanych promieni, dostosuj ogólny suwak 'Gęstość promieni'.

" - }, - "refIndex_note_popover": { - "message": "

*względny, jeśli znajduje się w innym szkle

Jeśli ten obiekt ma być symulowany z bezwzględnym współczynnikiem załamania światła n₁, ale jest umieszczony wewnątrz innego szkła o współczynniku załamania światła n₀, to należy tutaj ustawić współczynnik załamania światła na n₁/n₀. W bardziej skomplikowanych przypadkach, gdy kilka obiektów szklanych nakłada się na siebie, efektywny współczynnik odbicia tego obszaru jest równy iloczynowi współczynników odbicia poszczególnych szkieł.

" - }, - "stepSize_note_popover": { - "message": "

Wielkość kroku metody Eulera do rozwiązywania równania eikonału promienia - więcej informacji można znaleźć w funkcji 'step' i dokumentacji w pliku 'CircleGrinGlass.js'.

" - }, - "eps_CircleGrinGlass_note_popover": { - "message": "

Jednostki - [długość]^2.

Ta tolerancja numeryczna jest używana w funkcjach 'isOutsideGlass', 'isInsideGlass' i 'isOnBoundary' w pliku 'CircleGrinGlass.js'.

" - }, - "eps_GrinGlass_note_popover": { - "message": "

Jednostki - [długość].

Ta tolerancja numeryczna jest używana w funkcjach 'isOnBoundary' i 'countIntersections' w pliku 'GrinGlass.js'.

" - }, - "cauchyCoeff": { - "message": "Współczynnik Cauchy'ego" - }, - "transRatio": { - "message": "Współczynnik transmisji" - }, - "applytoall": { - "message": "Zastosuj do wszystkich" - }, - "duplicate": { - "message": "Powiel" - }, - "delete": { - "message": "Usuń" - }, - "unselect": { - "message": "Odznacz" - }, - "unselect_popover": { - "message": "Usuń zaznaczenie tego obiektu (kliknięcie prawym przyciskiem myszy pustego miejsca ma tę samą funkcję)." - }, - "showadvanced": { - "message": "Więcej opcji..." - }, - "processing": { - "message": "Przetwarzanie... Kliknij tutaj, aby zatrzymać." - }, - "contribute": { - "message": "Wnieś wkład" - }, - "github": { - "message": "GitHub" - }, - "about": { - "message": "O aplikacji" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "message": "Pomóż nam przetłumaczyć tę aplikację" - }, - "translated": { - "message": "przetłumaczone" - }, - "undo_popover": { - "message": "Cofnij ostatnią czynność. (Ctrl+Z)" - }, - "redo_popover": { - "message": "Ponów ostatnią czynność. (Ctrl+Y)" - }, - "reset_popover": { - "message": "Zresetuj wszystkie zmiany." - }, - "save_popover": { - "message": "Zapisz bieżącą scenę jako plik." - }, - "open_popover": { - "message": "Otwórz istniejący plik lub obraz tła. Obraz tła zostanie wyświetlony z punktu początkowego współrzędnych. (Lub upuść plik)" - }, - "get_link_popover": { - "incomplete": true, - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "message": "Adres URL jest zbyt długi i może nie działać na niektórych platformach. Może być konieczne użycie \"Zapisz\" i zamiast tego udostępnienie pliku." - }, - "export_svg_warning": { - "message": "Eksportuj do SVG. Mieszanki kolorów i względne współczynniki załamania światła poniżej 1 nie są obsługiwane." - }, - "export_ray_count_warning": { - "incomplete": true, - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "message": "Przejdź do strony Galerii, aby załadować przykład." - }, - "tool_SingleRay_popover": { - "message": "Pojedynczy promień światła określony przez dwa punkty. (Przeciągnij lub kliknij, aby utworzyć. Pierwszy punkt to źródło, wysyłające promień w kierunku drugiego punktu.)" - }, - "tool_Beam_popover": { - "message": "Z odcinka wyłania się równoległa lub rozbieżna wiązka promieni o gęstości kontrolowanej przez suwak 'Gęstość promieni'. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_PointSource_popover": { - "message": "Promienie wychodzące z jednego punktu. Ich liczba regulowana jest za pomocą suwaka 'Gęstość promieni'. (Kliknij, aby utworzyć.)" - }, - "tool_AngleSource_popover": { - "message": "Źródło punktowe o zadanym kącie emisji." - }, - "tool_Mirror_popover": { - "message": "Symuluje odbicie światła w zwierciadle płaskim. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_ArcMirror_popover": { - "message": "Zwierciadło, którego powierzchnia w przekroju jest fragmentem okręgu, określonym za pomocą trzech punktów. (Przeciągnij lub kliknij, aby utworzyć. Pierwsze 2 punkty określają odstęp między końcami łuku, ostatni punkt określa promień krzywizny.)" - }, - "tool_ParabolicMirror_popover": { - "message": "Zwierciadło, którego powierzchnia w przekroju jest fragmentem paraboli, określonej za pomocą trzech punktów. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_CustomMirror_popover": { - "message": "Zwierciadło, którego kształt jest określony przez niestandardowe równanie y = f(x), gdzie (x,y) jest w przekształconych współrzędnych, w których dwoma punktami kontrolnymi są (-1,0) i (1,0). (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_BeamSplitter_popover": { - "message": "Zwierciadło odbijające pewien procent padającego światła. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_IdealMirror_popover": { - "message": "Idealnie 'zakrzywione' zwierciadło, dokładnie spełniające równanie (1/x + 1/y = 1/f). Ogniskową można ustawić bezpośrednio. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_PlaneGlass_popover": { - "message": "Symuluje załamanie i odbicie światła na granicy ośrodków. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_CircleGlass_popover": { - "message": "Szkło o przekroju kołowym, określonym przez środek i punkt na brzegu. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_CircleGrinGlass_popover": { - "message": "Szkło z konfigurowaną funkcją współczynnika załamania n(x,y) i kołową krawędzią. (Przeciągnij lub kliknij, aby utworzyć)." - }, - "tool_Glass_popover": { - "message": "Szkło o dowolnych kształtach, mających przekroje ograniczone odcinkami i fragmentami okręgów. (Kliknij, aby utworzyć odcinek; przeciągnij, aby utworzyć łuk; kliknij punkt początkowy, żeby zakończyć rysowanie.)" - }, - "tool_GrinGlass_popover": { - "message": "Szkło z konfigurowaną funkcją współczynnika załamania n(x,y) i wielokątną krawędzią. OSTRZEŻENIE: Obsługiwane są tylko proste wielokąty, w przeciwnym razie zachowanie jest nieprzewidywalne. (Kliknij, aby utworzyć odcinek, kliknij punkt początkowy po zakończeniu rysowania.)" - }, - "tool_IdealLens_popover": { - "message": "Idealna soczewka, która spełnia dokładnie równanie (1/x + 1/y = 1/f). Ogniskową można ustawić bezpośrednio. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_SphericalLens_popover": { - "message": "Soczewka sferyczna. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_CustomGlass_popover": { - "message": "Szkło o kształcie zdefiniowanym przez niestandardową nierówność f(x) < y < g(x), gdzie (x,y) jest w przekształconych współrzędnych, w których dwoma punktami kontrolnymi są (-1,0) i (1,0). (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_Blocker_popover": { - "message": "Przeszkoda - odcinek - pochłaniająca padające promienie. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_Aperture_popover": { - "message": "Para blokerów światła, które pochłaniają padające promienie. Rozmiar otworu można regulować symetrycznie. (Przeciągnij lub kliknij dwa punkty końcowe, aby utworzyć)." - }, - "tool_CircleBlocker_popover": { - "message": "Przeszkoda - okrąg - pochłaniająca padające promienie. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_DiffractionGrating_popover": { - "incomplete": true, - "message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)" - }, - "tool_Ruler_popover": { - "message": "Linijka odmierzająca odległość od punktu zero (pierwsze kliknięcie) do innego punktu (drugie kliknięcie). (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_Protractor_popover": { - "message": "Kątomierz określony przez środek (wierzchołek kąta - pierwsze kliknięcie) i inny punkt dla kierunku zerowego (drugie kliknięcie). Skala jest w stopniach. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_Detector_popover": { - "message": "Narzędzie do pomiaru szybkości przepływu energii (P), szybkości prostopadłego przepływu pędu (F⊥), i szybkości równoległego przepływu pędu (F∥) przez odcinek. (Przeciągnij lub kliknij, aby utworzyć odcinek). Jednostki są umowne." - }, - "tool_Detector_info_popover": { - "incomplete": true, - "message": "" - }, - "tool_TextLabel_popover": { - "message": "Etykieta tekstowa." - }, - "tool_LineArrow_popover": { - "message": "Odcinek lub strzałka. (Przeciągnij lub kliknij, aby utworzyć.)" - }, - "tool_Drawing_popover": { - "message": "Narzędzie do rysowania odręcznego. (Przeciągnij, aby narysować.)" - }, - "tool__popover": { - "message": "Przeciągnij, aby przesunąć widok. (Przeciąganie prawym przyciskiem myszy ma tę samą funkcję)." - }, - "mode_rays_popover": { - "message": "Pokaż promienie. Gdy 'Gęstość promieni' jest duża, wiązka pojawia się jako ciągła." - }, - "mode_extended_popover": { - "message": "Pokaż zarówno promienie, jak i ich przedłużenia. Kolor pomarańczowy wskazuje przedłużenia do tyłu, a szary do przodu.
Gdy opcja „Symuluj kolory” jest włączona, są one wyświetlane w kolorach źródłowych i zamiast tego wyróżniane linią przerywaną." - }, - "mode_images_popover": { - "message": "Pokaż położenie wszystkich obrazów. Żółte punkty oznaczają obrazy rzeczywiste, pomarańczowe obrazy pozorne, a szare (brak na tym zdjęciu) obiekty wirtualne. Zwróć uwagę, że niektórych obrazów nie można wykryć, jeśli 'Gęstość promieni' nie jest wystarczająco wysoka.
Gdy opcja „Symuluj kolory” jest włączona, są one wyświetlane w kolorach źródłowych i zamiast tego rozróżniane na podstawie wielkości kropek." - }, - "mode_observer_popover": { - "message": "Symuluje promienie i obrazy widziane z określonego miejsca. Obserwatora symbolizuje niebieskie kółko. Wszelkie przecinające je promienie uważa się za 'obserwowane'. Obserwator nie wie, gdzie faktycznie zaczynają się promienie, ale będzie mu się wydawało, że zaczynają się w pewnym punkcie (punktach), jeśli się tam przecinają. Promienie są pokazane na niebiesko, a punkty na żółto (rzeczywiste) lub pomarańczowo (pozorne). (Przeciągnij dużą niebieską kropkę, aby przesunąć obserwatora.)
Gdy opcja „Symuluj kolory” jest włączona, zamiast tego są one wyświetlane w kolorach źródłowych." - }, - "simulateColors_popover": { - "message": "Symulacja kolorów (długości fal) źródeł światła, mieszania kolorów, filtrowania kolorów przez filtry blokujące i lustra oraz dyspersji chromatycznej szkieł. Po wybraniu można ustawić te parametry dla tych obiektów. Aby symulować widma kolorów, należy nałożyć na siebie promienie o różnych długościach fal. Kolory wyświetlane na ekranie są jedynie przybliżone i mogą być bardzo niedokładne, gdy 'Gęstość promieni' jest zbyt wysoka lub zbyt niska." - }, - "rayDensity_popover": { - "message": "Określa liczbę promieni emitowanych przez belki i źródła punktowe. Ma to również wpływ na dokładność wykrywania obrazu i renderowania kolorów." - }, - "showGrid_popover": { - "message": "Określa widoczność siatki tła." - }, - "grid_popover": { - "message": "Określa, czy przyciągać do węzłów siatki." - }, - "lockObjs_popover": { - "message": "Określa, czy obiekty mogą być przenoszone, czy nie." - }, - "zoom_popover": { - "message": "Wielkość widoku w procentach." - }, - "help_popover": { - "incomplete": true, - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "message": "Pokaż okienka pomocy" - }, - "show_help_popups_popover": { - "message": "Określa, czy wyświetlać wyskakujące okienka pomocy po najechaniu kursorem na przyciski. (Załaduj ponownie stronę, aby zastosować.)" - }, - "show_json_editor": { - "incomplete": true, - "message": "Show JSON editorBeta" - }, - "show_json_editor_popover": { - "incomplete": true, - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "incomplete": true, - "message": "Show status box" - }, - "show_status_popover": { - "incomplete": true, - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "incomplete": true, - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "incomplete": true, - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "incomplete": true, - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "incomplete": true, - "message": "Grid Size" - }, - "observer_size": { - "incomplete": true, - "message": "Observer Size" - }, - "language": { - "message": "Język" - }, - "close": { - "message": "Zamknij" - }, - "advanced_help": { - "message": "Aby uzyskać zaawansowaną pomoc, zobacz ikonę pomocy w prawym dolnym rogu." - }, - "ray_count": { - "incomplete": true, - "message": "Number of ray segments: " - }, - "total_truncation": { - "incomplete": true, - "message": "Truncated brightness: " - }, - "brightness_scale": { - "incomplete": true, - "message": "Brightness Scale: " - }, - "time_elapsed": { - "incomplete": true, - "message": "Time elapsed (ms): " - }, - "force_stopped": { - "incomplete": true, - "message": "Force stopped." - }, - "mouse_coordinates": { - "incomplete": true, - "message": "Mouse coordinates: " - }, - "modules_tutorial": { - "incomplete": true, - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "incomplete": true, - "message": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior." - }, - "import_modules": { - "incomplete": true, - "message": "Import Modules..." - }, - "import_modules_title": { - "incomplete": true, - "message": "Import Modules" - }, - "modules_url": { - "incomplete": true, - "message": "../modules/modules.html" - }, - "remove_module": { - "incomplete": true, - "message": "Remove module" - }, - "module_conflict": { - "incomplete": true, - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "incomplete": true, - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/pl/gallery.json b/locales/pl/gallery.json new file mode 100644 index 00000000..054986ff --- /dev/null +++ b/locales/pl/gallery.json @@ -0,0 +1,356 @@ +{ + "galleryPage": { + "title": "Galeria Promieni Optycznych", + "description": "Jest to zbiór symulacji wykonanych za pomocą [aplikacji internetowej](/simulator), którą można wykorzystać do tworzenia takich interaktywnych demonstracji z optyki. Zapraszamy do dodawania nowych elementów. Aby uzyskać więcej informacji, zobacz [przewodnik dotyczący wkładu](/contributing/gallery). Aby zgłosić błąd, [otwórz problem w GitHub](/github/issues) lub wyślij wiadomość e-mail na adres [ray-optics@phydemo.app](/email).", + "categories": { + "title": "Kategorie", + "reflection": "Odbicie", + "refraction": "Załamanie", + "lens": "Soczewka", + "combinationOfLenses": "Układy soczewek", + "grinOptics": "Optyka gradientowa (GRIN)", + "miscellaneous": "Różne" + }, + "contributors": "Osoba wnosząca wkład: {{contributors}}", + "openInSimulator": "Otwórz w symulatorze" + }, + "galleryData": { + "common": { + "warningthesequenceof": "Ostrzeżenie: sekwencja pojawiania się światła nie reprezentuje rzeczywistej prędkości światła - znaczenie ma tylko obraz końcowy." + }, + "imagesFormedByTwoMirrors": { + "title": "Obrazy w układzie dwóch zwierciadeł", + "description": "Symulacja pokazuje obrazy utworzone przez dwa zwierciadła płaskie. Zielone \"L\" to przedmiot. Jeśli kąt między dwoma zwierciadłami wynosi \\(\\frac{360^\\circ}{n}\\), wtedy powstanie \\(n-1\\) pozornych obrazów (pomarańczowe L). Można przeciągnąć punkt końcowy każdego ze zwierciadeł, aby zmienić kąt między nimi." + }, + "parabolicMirror": { + "title": "Zwierciadło paraboliczne", + "description": "Symulacja pokazuje właściwości ogniskowania zwierciadła parabolicznego." + }, + "hyperbolicMirror": { + "title": "Zwierciadło hiperboliczne", + "description": "Demonstracja właściwości odbicia od zwierciadła hiperbolicznego: Promienie świetlne biegnące od jednego ogniska w kierunku zwierciadła hiperbolicznego będą odbijać się biegnąc tak, że ich przedłużenia wypadają w drugim ognisku.\n\nDwa ogniska hiperboli to punkty aplanatyczne (patrz [Punkty aplanatyczne](/gallery/aplanatic-points)).", + "theorangeraysareimag": "Promienie pomarańczowe są pozornymi promieniami (przedłużenia odbitych promieni żółtych).\nTe pozorne promienie skupiają się w drugim ognisku.", + "pointlightsourceaton": "Umieść źródło światła w ognisku" + }, + "retroreflectors": { + "title": "Retroreflektory", + "description": "symulacja dwóch rodzajów retroreflektorów:\n\n1. Retroreflektor narożny.\n2. Retroreflektor kocie oko.", + "dragtorotatethebeam": "przeciągnij tutaj\naby obrócić wiązkę", + "catseyeretroreflecto": "Retroreflektor kocie oko", + "cornerretroreflector": "Retroreflektor narożny" + }, + "periscope": { + "title": "Peryskop", + "description": "Symulacja peryskopu wykonanego z dwóch płaskich zwierciadeł i kilku elementów blokujących światło.", + "observerseyenottosca": "Oko obserwatora (nie w skali)" + }, + "newtonianTelescope": { + "title": "Teleskop Newtona", + "description": "Model teleskopu Newtona z okularem Plössla." + }, + "penroseUnilluminableRoom": { + "title": "Nieoświetlony pokój Penrose'a", + "description": "Niemożliwy do oświetlenia pokój Penrose'a jest zbudowany z luster eliptycznych, kołowych i liniowych. Ma tą interesującą właściwość, że źródło punktowe (zielone) w pomieszczeniu nie oświetli całego pomieszczenia, bez względu na to, gdzie je umieścisz. Możesz przeciągnąć zielony punkt, aby przesunąć źródło.", + "nomatterwhereyouputt": "Bez względu na to, gdzie umieścisz źródło punktowe, nie oświetli ono całego pomieszczenia.\nOstrzeżenie: z powodu błędu numerycznego po pewnym czasie może nadal świecić." + }, + "opticalCavity": { + "title": "Wnęka optyczna z dwoma zwierciadłami", + "description": "Jest to symulacja promieni wewnątrz wnęki optycznej z dwoma zwierciadłami. Biorąc pod uwagę, że długość wnęki wynosi \\(d\\), a promienie krzywizny jej zwierciadeł wynoszą odpowiednio \\(R_1\\) i \\(R_2\\) (z konwencją, że \\(R>0\\) dla zwierciadła wklęsłego), to wnęka optyczna jest stabilna (co oznacza, że dla każdego promienia wychodzącego z jednego zwierciadeł w kierunku drugiego zwierciadła trajektoria nierozbieżna jest gwarantowana dla dostatecznie wysokich zwierciadeł), wtedy i tylko wtedy, gdy \\(0\\leq (1-\\frac {d}{R_1})(1-\\frac {d}{R_2})\\leq 1\\). W tej symulacji zakładamy, że zwierciadła są idealnie zakrzywionymi zwierciadłami, co oznacza, że \\(f=\\frac{R}{2}\\) i sprowadza poprzedni warunek stabilności do postaci \\(0\\leq (1-\\frac {d}{2f_1})(1-\\frac {d}{2f_2})\\leq 1\\). [Tutaj](/gallery/resonator) podobna symulacja ze zwierciadłami sferycznymi, gdzie pierwszy warunek stabilności jest spełniony w przybliżeniu przyosiowym.", + "clickholdleftmouseto": "Kliknij + przytrzymaj lewy przycisk myszy\naby przesunąć promień", + "d400intheresonatorsb": "d = 400 w rezonatorach poniżej", + "confocalresonator": "Rezonator konfokalny", + "concentricresonator": "Rezonator koncentryczny", + "concaveconvexresonat": "Rezonator wklęsło-wypukły", + "planoconcaveresonato": "Rezonator płasko-wklęsły" + }, + "resonator": { + "title": "Rezonator płasko-wklęsły", + "description": "To jest demonstracja rezonatora płasko-wklęsłego. Jeśli odległość między zwierciadłami jest większa niż promień krzywizny, rezonator jest niestabilny. Jeśli odległość między zwierciadłami jest mniejsza lub równa promieniowi krzywizny, otrzymujemy stabilny tryb rezonatora.", + "flatmirror": "Zwierciadło płaskie", + "sphericalconcavemirr": "Sferyczne zwierciadło wklęsłe", + "unstableresonator": "Niestabilny rezonator", + "stableresonator": "Stabilny rezonator" + }, + "mazeSolution": { + "title": "Rozwiązanie labiryntu", + "description": "Symulacja biegu promienia światła wysłanego w labiryncie, wielokrotnie odbijanego przez ściany. Większy i mniejszy czerwony kwadrat wewnątrz labiryntu (widoczne na zrzucie ekranu poniżej) reprezentują odpowiednio punkt wysłania i początkowy kierunek promienia światła. W przypadku niektórych początkowych orientacji, promień światła wychodzi z labiryntu, a tym samym, cofając się po torze promienia, można zasadniczo znaleźć rozwiązanie labiryntu.", + "controltherayorigina": "Kontroluj początek promienia i początkowy kierunek\nprzeciągając górny i dolny znacznik (odpowiednio).", + "notethatthesimulatio": "Należy zauważyć, że przetwarzanie symulacji kończy się tylko raz\ni wtedy komunikat przetwarzania w lewym dolnym rogu zniknie.", + "mazeexit": "Wyjście z labiryntu" + }, + "specularAndDiffuseReflection": { + "title": "Odbicie zwierciadlane i rozproszone", + "description": "Identyczne wiązki promieni padają na powierzchnię gładką i chropowatą, ilustrując różnicę między odbiciem zwierciadlanym i rozproszonym.", + "specular": "Zwierciadlane", + "diffuse": "Rozproszone" + }, + "chaffCountermeasure": { + "title": "Dipole odbijające (chaff)", + "description": "Jest to jakościowa symulacja systemu przeciwdziałania namiarom radarowym (pomijając efekty dyfrakcyjne).", + "plane": "Płaszczyzna", + "radar": "Radar", + "chaff": "Chaff" + }, + "reflect": { + "title": "Odbicie i załamanie", + "description": "Symulacja pokazuje odbicie i załamanie na powierzchni." + }, + "internalReflection": { + "title": "Odbicie wewnętrzne", + "description": "Symulacja pokazuje refrakcję i wewnętrzne odbicie na powierzchni." + }, + "prisms": { + "title": "Pryzmaty", + "description": "Symulacja pokazuje pryzmat prostokątny, pryzmat Porro (dachowy), pryzmat romboidalny, pryzmat Gołębicy i pryzmat pentagonalny.", + "rhomboid": "romboidalny", + "rightangle": "prostokątny", + "porro": "Porro", + "dove": "Gołąb", + "pentaprism": "pentagonalny" + }, + "beamDirectors": { + "title": "Kierowanie wiązką światła", + "description": "Symulacja bipryzmatu regularnego i Fresnela. Bipryzmat może skierować padającą skolimowaną wiązkę w dwóch kierunkach, w zależności od kąta wierzchołkowego.", + "fresnelbiprism": "Bipryzmat Fresnela", + "biprism": "Bipryzmat" + }, + "apparentDepth": { + "title": "Pozorna głębokość", + "description": "Kiedy patrzysz z powietrza na obiekt pod wodą, głębokość na jakiej się znajduje wydaje się być mniejsza niż w rzeczywistości. Złudzenie to jest spowodowane załamaniem światła i zostało zademonstrowane w tej symulacji. Pozorna głębokość zależy od położenia obserwatora, co można zademonstrować, przeciągając niebieskie kółko.", + "observedimageorange": "obserwowany obraz (pomarańczowy)", + "observer": "obserwator", + "objectunderwatergree": "obiekt pod wodą (zielony)" + }, + "bendedPencil": { + "title": "Zgięty ołówek", + "description": "Jest to symulacja obrazu postrzeganego przez nas, gdy patrzymy z góry na częściowo zanurzony w szklance wody ołówek. Załamanie promieni powoduje, że ołówek może wyglądać zarówno na wygięty, jak i złamany (w zależności od położenia oczu obserwatora). Jednak w tej symulacji zginanie jest bardziej wyraźne. Możesz sprawdzić symulację [Złamany ołówek](/gallery/broken-pencil), gdzie to drugie złudzenie jest bardziej wyraźne.", + "bentpencilyellowimag": "zagięty ołówek (żółty)\nobraz na siatkówce", + "dielectricmaterial": "materiał dielektryczny", + "originalpencilgreen": "ołówek oryginalny (zielony)", + "observerseye": "oko obserwatora", + "ignoretheorangesquar": "Zignoruj pomarańczowe kwadraty!" + }, + "brokenPencil": { + "title": "Złamany ołówek", + "description": "Jest to symulacja obrazu postrzeganego przez nas, gdy patrzymy z boku na częściowo zanurzony w szklance wody ołówek. Załamanie promieni powoduje, że ołówek może wyglądać zarówno na wygięty, jak i złamany (w zależności od położenia oczu obserwatora). Jednak w tej symulacji złamanie jest bardziej wyraźne. Możesz sprawdzić symulację [Zgięty ołówek](/gallery/bended-pencil), gdzie to drugie złudzenie jest bardziej wyraźne.", + "brokenpencilyellowim": "złamany ołówek (żółty)\nobraz na siatkówce" + }, + "chromaticDispersion": { + "title": "Dyspersja chromatyczna", + "description": "Symulacja pokazuje dyspersję chromatyczną za pomocą wiązki światła białego i trójkątnego pryzmatu. Biały kolor tutaj powstaje przez mieszanie kolorów czerwonego, pomarańczowego, żółtego, zielonego, cyjanowego, niebieskiego i fioletowego.", + "dragheretoadjustbeam": "przeciągnij tutaj\n aby ustawić szerokość wiązki", + "dragheretorotatethep": "przeciągnij tutaj\naby obrócić pryzmat" + }, + "rainbows": { + "title": "Tęcze", + "description": "Symulacja pokazuje formowanie się tęczy pierwotnej, tęczy wtórnej i ciemnego pasa Aleksandra. Tutaj widmo światła słonecznego jest przybliżone przez zmieszanie kolorów czerwonego, pomarańczowego, żółtego, zielonego, cyjanowego, niebieskiego i fioletowego. Promienie wychodzące dla pierwotnej/wtórnej tęczy wynikają z jednego/dwóch wewnętrznych odbić w kropli deszczu (można to zobaczyć, ustawiając niską gęstość promieni i przeciągając kroplę deszczu). Należy zauważyć, że nie są to całkowite wewnętrzne odbicia, więc intensywność promieni wychodzących jest znacznie niższa niż promieni padających. Ponieważ [minimalne kąty odchylenia](/gallery/minimum-deviation-angle) zależą od długości fali, różne kolory kumulują się pod różnymi kątami. Stąd powstają kolory tęczy. Z dala od minimalnych kątów promienie nie kumulują się, więc wszystkie kolory są słabe i mieszają się ze sobą, tworząc przyćmiony biały (lub „szary”) kolor pod kątami tuż na zewnątrz obu tęcz. Z drugiej strony żadne promienie nie docierają w obszar kąta między tęczami, tworząc ciemny pas Aleksandra.", + "thesearethecolorspro": "Są to kolory powstałe z pojedynczej kropli deszczu.\nKońcowe tęcze, które widzimy, są spowodowane ogromną liczbą kropel deszczu na niebie,\nz których każda daje obserwatorowi jeden kolor (pod odpowiednim kątem).", + "secondaryrainbow": "Tęcza wtórna", + "alexandersdarkband": "Ciemny pas Aleksandra", + "raindrop": "Kropla deszczu", + "primaryrainbow": "Tęcza pierwotna", + "sunlight": "Światło słoneczne" + }, + "minimumDeviationAngle": { + "title": "Minimalny kąt odchylenia", + "description": "Definicja kąta odchylenia promienia padającego na element optyczny zależy od kontekstu - na poniższym zrzucie ekranu możesz zobaczyć jego definicję dla pryzmatu trójkątnego i sferycznego. W przykładach zawartych w tej symulacji kąt odchylenia jako funkcja kąta padania promienia wchodzącego do elementu optycznego ma lokalne minimum, które nazywa się \"minimalnym kątem odchylenia\". To lokalne minimum może wyjaśniać zjawiska optyczne, takie jak [tęcze](/gallery/rainbows) i halo - z powodu tego lokalnego minimum, odchylone promienie gromadzą się w określonych kierunkach, tworząc \"optyczną kaustykę\" (jak widać w przykładzie C w symulacji), którą postrzegamy jako tęcze/halo.", + "inexamplesaandbbyrot": "W przykładach A i B, obracając pryzmaty między punktami A1 do A2 i B1 do B2 i zmieniając w ten sposób\nkąt padania promienia wpadającego do elementu optycznego, można łatwo zauważyć, że minimalny\nkąt odchylenia uzyskuje się gdzieś pomiędzy parą punktów.\n(w przykładzie A kąt odchylenia mierzony jest względem osi poziomej, natomiast w przykładzie B\njest mierzony względem osi pionowej).\n\nTeraz powiększ przykład C (używając powiększenia symulacyjnego) i rozszerz dwie wiązki (czerwoną i fioletową, a\nich przecięcie wygląda na różowe. Jest to faktycznie to samo, co obracanie pryzmatu sferycznego w\nprzykładzie B, zmieniające w ten sposób kąt padania promienia wchodzącego) i zobacz, że od punktu\nC1 do C2 promienie wychodzące wstecz kumulują się w dół w dwa odrębne promienie - czerwony i fioletowy\n(\"kaustyka optyczna\")– minimalny kąt odchylenia występuje koło punktu C2 i zależy od\ntdługości fali światła (kolor). Następnie, podczas rozszerzania dwóch wiązek od punktu C2 do C3,\npromienie wychodzące wstecz odwracają swój kierunek w górę.", + "examplea": "Przykład - A", + "examplec": "Przykład - C", + "exampleb": "Przykład - B", + "usethebuiltinzoomtob": "Użyj wbudowanego zoomu, aby lepiej operować symulacją", + "deviationangle": "Kąt odchylenia", + "incidenceangle": "Kąt padania" + }, + "aplanaticPoints": { + "title": "Punkty aplanatyczne", + "description": "Punkty aplanatyczne układu optycznego to szczególne punkty na jego osi optycznej, takie, że \"promienie wychodzące z jednego z nich zbiegają się lub rozchodzą się z drugiego punktu\".\n\n- Elipsa: dwa ogniska eliptycznej soczewki/zwierciadła są punktami aplanatycznymi, ponieważ światło emitowane z jednego ogniska zbiega się w kierunku drugiego.\n- Sfera: soczewka sferyczna ma dwa punkty aplanatyczne, wewnątrz i na zewnątrz kuli - więcej szczegółów w symulacji.\n- Hiperbola: dwa ogniska [modelu zwierciadła hiperbolicznego](/gallery/hyperbolic-mirror) są również punktami aplanatycznymi.\n\nJeśli dane są dwa punkty o odciętych \\(x_1\\) i \\(x_2\\) oraz identycznych rzędnych, i współczynniki załamania światła na zewnątrz i wewnątrz naszego elementu optycznego wynoszą odpowiednio \\(n_1\\) i \\(n_2\\), to aby te dwa punkty były punktami aplanatycznymi, granica naszego elementu optycznego musi spełniać równanie\\begin{equation}k_1 n_1 \\sqrt{ (x - x_1)^2 + y^2} + k_2 n_2 \\sqrt{ (x - x_2)^2 + y^2} = E\\end{equation}, gdzie \\(k_i=1\\) or \\(-1\\), jeśli promień łączący \\(x_i\\) i granicę naszego elementu optycznego jest odpowiednio rzeczywisty lub pozorny, a \\(E\\) jest stałą, dla której to równanie ma nietrywialne rozwiązanie. To równanie (które można wyprowadzić za pomocą zasady Fermata) jest równaniem owalu Kartezjusza, którego krzywe stożkowe są przypadkami szczególnymi.", + "clickontheextendedra": "Kliknij przycisk \"Promienie rozszerzone\", aby sprawdzić, czy światło emitowane ze źródła światła w soczewce sferycznej (punkt A)\nbędzie odchylać się od innego punktu na osi optycznej poza soczewką sferyczną (punkt B) bez aberracji sferycznej.\nPunkty A i B są przykładem punktów aplanatycznych sfery, dla której (k1, k2, n1, n2, x1, x2, E)=(1, -1, 1.5, 1, 3 * 20, -4.5 * 20, 0) relative to the marked Y axis,\ngdzie x1,x2 to odpowiednio poziome współrzędne punktów A, B (każda komórka siatki ma wymiary 20 na 20).\nW podobny sposób ogniska elipsy (punkty C i D) są przykładem punktów aplanatycznych elipsy, dla których (k1, k2, n1, n2, E)=(1, 1, 1.5, 1.5, > 0)", + "sphericallens": "Soczewka sferyczna", + "ellipticallens": "Soczewka eliptyczna", + "yaxis": "oś Y" + }, + "concaveLens": { + "title": "Soczewka wklęsła", + "description": "Symulacja pokazuje soczewkę wklęsłą rozpraszającą wiązkę." + }, + "convexLens": { + "title": "Soczewka wypukła", + "description": "Symulacja pokazuje soczewkę wypukłą skupiającą wiązkę." + }, + "lensImages": { + "title": "Obrazy w soczewce", + "description": "Symulacja pokazuje obrazy wiązki i źródeł punktowych wytwarzanych przez idealne soczewki." + }, + "transverseAndLongitudinalMagnification": { + "title": "Powiększenie poprzeczne i wzdłużne", + "description": "Symulacja powiększenia poprzecznego i wzdłużnego dla idealnej soczewki o ogniskowej \\(f\\). Powiększenie poprzeczne (zwane także liniowym) i wzdłużne to odpowiednio \\(M_T=1-\\frac{u}{f}\\) i \\(M_L=\\frac{dv}{du}\\), gdzie \\(u\\) and \\(v\\) to odpowiednio odległość przedmiotu i obrazu od naszej idealnej soczewki. Dla idealnej soczewki zachodzi również \\(M_L=-(M_T)^2\\)", + "inthisexamplewehavey": "W tym przykładzie mamy y'_j - y'_k = M_T * (y_j - y_k), gdzie j,k∈{0,1,2,3,4,5}.\nDlatego np. powiększenie poprzeczne obiektu punktowego (x_0,y_0) wynosi M_T = -3 i możemy obliczyć - \n(x'_0 - x'_1)/(x_1 - x_0) ≈ -0.3699\n(x'_0 - x'_2)/(x_2 - x_0) ≈ -0.7297\n(x'_0 - x'_3)/(x_3 - x_0) ≈ -1.4211\n(x'_0 - x'_4)/(x_4 - x_0) ≈ -2.4545\n(x'_0 - x'_5)/(x_5 - x_0) = -5.4\n.\n.\n.\n(Stosunek będzie zbieżny do powiększenia podłużnego: M_L = - (M_T)^2 = -9)", + "rightclickonarealobj": "Kliknij prawym przyciskiem myszy (rzeczywisty) obiekt, aby wyświetlić jego współrzędne.\nZielone kwadraty to rzeczywiste źródła punktowe, podczas gdy żółte kwadraty to obrazy." + }, + "vanishingPoint": { + "title": "Punkt zbiegu", + "description": "Niektóre układy optyczne odwzorowują nieskończone równoległe proste na linie na płaszczyźnie obrazu, które spotykają się w jednym punkcie, tworząc złudzenie, że spotykają się \"w nieskończoności\". Ten pojedynczy punkt nazywany jest punktem zbiegu.\n\nDla układu optycznego składającego się z idealnej soczewki o ogniskowej \\(f\\), położonej na płaszczyźnie \\(XY\\), tak że jej oś optyczna pokrywa się z osią \\(X\\)(poziomą) i soczewka pokrywa się z osią \\(Y\\), punkt zbiegu linii o współczynniku kierunkowym \\(m\\), umieszczonaj w obszarze \\(x<0\\), ma współrzędne \\((f,m f)\\).", + "youcanverifythatapai": "Możesz sprawdzić, że para prostych równoległych o współczynniku kierunkowym - m skupiana jest przez idealną soczewkę w punkcie o współrzędnych (f,m∙f),\nklikając przycisk \"Siatka\" i zauważając, że każda komórka siatki ma wymiary 20 na 20.\nMożna również sprawdzić, jak zmiana ogniskowej idealnej soczewki - f, wpływa na punkty zbiegu.", + "thesepairofparallell": "Ta para równoległych prostych zbiega się w punkcie B", + "thesepairofparallell1": "Ta para równoległych prostych zbiega się w punkcie A", + "notethatthesepairsof": "Zauważ, że te pary równoległych linii nie są w rzeczywistości nieskończone." + }, + "monochromaticAberrations": { + "title": "Aberracje monochromatyczne", + "description": "To jest symulacja różnych aberracji monochromatycznych:\n\n1. Aberracja sferyczna.\n2. Aberracja komatyczna.\n3. Aberracja rozogniskowania.\n4. Aberracja krzywizny pola.", + "defocusaberration": "Rozogniskowanie", + "sphericalaberration": "Aberracja sferyczna", + "screen": "Ekran", + "fieldcurvatureaberra": "Krzywizna pola", + "commaaberration": "Koma" + }, + "chromaticAberration": { + "title": "Aberracja chromatyczna", + "description": "Ta symulacja pokazuje aberrację chromatyczną w soczewce sferycznej. Tutaj biały kolor powstaje przez mieszanie kolorów czerwonego, pomarańczowego, żółtego, zielonego, cyjanowego, niebieskiego i fioletowego. Ogniskowa dla światła czerwonego jest największa, a dla fioletowego najmniejsza." + }, + "hyperbolicLens": { + "title": "Soczewka hiperboliczna", + "description": "Jest to symulacja i porównanie soczewek hiperbolicznych i sferycznych. Obie soczewki mają identyczne ogniskowe, ale w przeciwieństwie do soczewki sferycznej, soczewka hiperboliczna może skupić równoległą wiązkę światła monochromatycznego do jednego punktu (pomijając falową naturę światła - czyli w przybliżeniu optyki geometrycznej) bez aberracji sferycznych.", + "thefocallengthofthis": "Ogniskowa tej soczewki sferycznej (w przybliżeniu przyosiowym) wynosi:\nf=R/(n-1)=200/(1.5-1)=400", + "thefocallengthofthis1": "Ogniskowa tej soczewki hiperbolicznej wynosi:\nf = |C| ∙ sqrt(n^2 - 1) / (n - 1) = K ∙ sqrt(0.8) ∙ sqrt(1.5^2 - 1) / (1.5 - 1) = 400\ngdzie równanie tej hiperboli to:\ny(x) = (a/K) - sqrt( ((x/K)^2 + (C/K)^2) / (n^2 - 1) )\n= 1.5 - sqrt( (0.8 + (x / 200)^2) / (1.5^2 - 1) )\ntaka, że K jest stałą przeliczeniową wymiarów równania na wymiary siatki - dla tej soczewki hiperbolicznej K=200.\n(na przykład 0 0\\) i \\(\\alpha = \\arctan k\\) to stały kąt między dwiema stycznymi w punkcie przecięcia koncentrycznej spirali logarytmicznej z okręgiem (jak pokazuje [ta](https://en.wikipedia.org/wiki/Logarithmic_spiral#/media/File:Logspiral.gif) animacja), to \\(n(r) ∝ \\frac{1}{r}\\) (można to wykazać zapisując ścieżkę optyczną we współrzędnych biegunowych i wykorzystując zasadę Fermata).", + "thecircularblockeris": "Kołowy bloker znajduje się w środku,\naby uniknąć osobliwości współczynnika załamania" + }, + "luneburgLens": { + "title": "Soczewka Luneburga", + "description": "Symulacja soczewki Luneburga, która jest sferycznym dielektrykiem o współczynniku załamania światła \\(\\rho) = \\sqrt{n_0-(\\frac{\\rho}{R})^2} \\), gdzie \\(n_0=2\\) to współczynnik załamania w środku soczewki soczewki, \\(R=100\\) to promień soczewki, a \\(\rho\\) to odległość od środka soczewki.\n\nGórny dielektryk składa się z \\(N=20\\) koncentrycznych soczewek sferycznych o promieniu \\(R_i=5(N+1-i)\\) i współczynniku załamania światła \\(n_i = \\sqrt{n_0-(\\frac{R_i}{R})^2} \\), gdzie \\(i=1,...,N\\). Jednakże, ponieważ ten symulator oblicza efektywny współczynnik załamania światła elementu optycznego poprzez pomnożenie współczynnika załamania elementu przez współczynniki załamania elementów optycznych, które są w nim osadzone, współczynnik załamania \\(i\\)-tej koncentrycznej soczewki sferycznej jest określony wzorem \\(n_{i}^\\text{numerical}=\\frac{n_i}{n_{i-1}}\\).\n\nDolny dielektryk jest materiałem gradientowym o współczynniku załamania \\(n(r)\\)." + }, + "maxwellFisheyeLens": { + "title": "Soczewka rybie oko Maxwella", + "description": "To jest symulacja soczewki typu rybie oko Maxwella, która jest sferycznym dielektrykiem o współczynniku załamania światła \\(n(\\rho) = \\frac{n_0}{1+(\\frac{\\rho}{R})^2} \\), gdzie \\(n_0=2\\) to współczynnik załamania w środku soczewki soczewki, \\(R=100\\) to promień soczewki, a \\(\\rho\\) to odległość od środka soczewki.\n\nGórny dielektryk składa się z \\(N=20\\) koncentrycznych soczewek sferycznych o promieniu \\(R_i=5(N+1-i)\\) i współczynniku załamania światła \\(n_i = \\frac{n_0}{1+(\\frac{R_i}{R})^2} \\), gdzie \\(i=1,...,N\\). Jednakże, ponieważ ten symulator oblicza efektywny współczynnik załamania światła elementu optycznego poprzez pomnożenie współczynnika załamania elementu przez współczynniki załamania elementów optycznych, które są w nim osadzone, współczynnik załamania \\(i\\)-tej koncentrycznej soczewki sferycznej jest określony wzorem \\(n_{i}^\\text{numerical}=\\frac{n_i}{n_{i-1}}\\).\n\nDolny dielektryk jest materiałem gradientowym o współczynniku załamania \\(n(r)\\)." + }, + "singleRayDemo": { + "title": "Pojedynczy promień", + "description": "Symulacja pokazująca odbicie i załamanie pojedynczego promienia." + }, + "sphericalLensAndMirror": { + "title": "Soczewka sferyczna i zwierciadło sferyczne", + "description": "Symulacja pokazuje ciągłą wiązkę przechodzącą przez soczewkę sferyczną i zwierciadło sferyczne." + }, + "interrogationRoom": { + "title": "Pokój przesłuchań", + "description": "Jest to symulacja lustra weneckiego (właściwym określeniem jest lustro fenickie) w pokoju przesłuchań. Obserwator w ciemnym pokoju (najlepiej, gdy wnętrze ciemnego pokoju nie emituje/odbija światła, a także pochłania całe światło wpadające z pokoju przesłuchań) jest w stanie zajrzeć do wnętrza pokoju przesłuchań, ponieważ światło wytwarzane przez lampę w pokoju przesłuchań jest rozpraszane i odbierane przez obserwatora przez lustro weneckie, podczas gdy podejrzany widzi tylko wnętrze pokoju przesłuchań oraz odbicie swoje i lampy (ponieważ nie dociera do niego światło z ciemnego pokoju).", + "pressonallimagestose": "Naciśnij \"Wszystkie obrazy\", aby zobaczyć lokalizację\nodbicia lampy i obiektów\nw płaszczyźnie obrazu podejrzanego i obserwatora", + "darkroom": "Ciemny pokój", + "twowaymirror": "Lustro weneckie", + "lamp": "Lampa", + "interrogationroom": "Pokój przesłuchań", + "observerseyeris": "Oczy obserwatora", + "suspectseyeris": "Oczy podejrzanego", + "thelampobjectinthesu": "Oświetlony obiekt w płaszczyźnie obrazu podejrzanego", + "thelampsreflectionin": "Odbicie lampy w płaszczyźnie obrazu podejrzanego", + "thelampsreflection": "Odbicie lampy", + "thelampobjectintheob": "Oświetlony obiekt w płaszczyźnie obrazu obserwatora" + }, + "cameraObscura": { + "title": "Camera obscura", + "description": "To jest symulacja Camera obscura (łac. ciemna komnata). W ciemnym pokoju można zobaczyć odwrócony obraz obiektów na zewnątrz, rzutowany na ścianie (bez użycia dodatkowego obiektywu).", + "observer2": "Obserwator", + "objectsoutside": "Obiekty na zewnątrz", + "darkroom1": "Ciemny pokój" + }, + "nlSimulation": { + "title": "Lornetki NL", + "description": "Symulacja przedstawia zgrubny szkic zasady działania lornetki Swarovski NL." + }, + "einsteinRingRefocusedToSingleImageViaEyepiece": { + "title": "Pierścień Einsteina ponownie zogniskowany przez okular na pojedynczy obraz", + "description": "Model okularu/soczewki, który mógłby być użyty w dowolnym teleskopie naukowym, który odwróci \"halo\" i skupi pierścień Einsteina z powrotem do pierwotnej postaci, jednocześnie rozpraszając światło gwiazdy lub masywnego obiektu, który spowodował utworzenie pierścienia." + }, + "blackCatBecomesWhite": { + "title": "\"Czarny kot staje się biały\" demo", + "description": "\"Czarny kot staje się biały\" to demonstracja popularnonaukowa, w której część figurki znika po włożeniu do wody. Składa się z następujących kroków:\n\n1. Narysuj postać (np. czarnego kota) na kartce papieru.\n2. Włóż kartkę do przezroczystej, szczelnie zamykanej plastikowej torby.\n3. Narysuj część figury (np. obwódkę kota) lub inną figurę na plastikowej powierzchni. Po włożeniu do wody postać narysowana na papierze znika, ale nie część narysowana na plastikowej powierzchni.\n\nTa symulacja wyjaśnia, jak to działa.", + "whenthebagisunderwat": "Gdy torebka znajduje się pod wodą, światło od papieru nie dociera do oczu,\nwięc widzimy tylko postać narysowaną na plastikowej powierzchni.", + "lightfromtheplastics": "Światło od plastikowej powierzchni", + "lightfromthepaper": "Światło od papieru", + "eyes": "Oczy" + }, + "dichroicRbgSplitterAndCombiner": { + "title": "Dichroiczny rozdzielacz i sumator RGB", + "description": "Ta symulacja demonstruje rozdzielanie i łączenie wiązek RGB przy użyciu zwierciadeł dichroicznych.", + "rgbcomponentsplitter": "Rozdzielacz i sumator komponentów RGB", + "lightsource": "Źródło światła", + "dichroiccube": "Kostka dichroiczna", + "beamcombiner": "Sumator wiązki" + }, + "ganBasedLcdPixel": { + "title": "Piksel LCD", + "description": "Model piksela LCD. Symuluje działanie warstw wyświetlacza mikroledowego i sposób, w jaki nasze oczy postrzegają piksel.", + "pixelsaresosmallthel": "Piksele są tak małe, że światło\nnaszym oczom wydaje się być zmieszane", + "changetherateoftrans": "Zmień szybkość transmisji\nAby utworzyć dowolną wartość RGB", + "blueledbacklight": "Niebieskie podświetlenie LED", + "yellowphosphor": "Fosfor żółty", + "liquidcrystal": "Ciekły kryształ", + "lightfilters": "Filtry światła", + "pixelasvisibletoview": "Piksel, tak jak widzi go obserwator", + "notpartoflcddisplay": "Nie jest częścią wyświetlacza LCD" + } + } +} \ No newline at end of file diff --git a/locales/pl/main.json b/locales/pl/main.json new file mode 100644 index 00000000..65028e73 --- /dev/null +++ b/locales/pl/main.json @@ -0,0 +1,203 @@ +{ + "meta": { + "languageName": "polski", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "Symulacja biegu promieni", + "shortName": "Optyka geometryczna", + "description": "Aplikacja internetowa open source umożliwiająca symulację odbicia i załamania światła." + }, + "pages": { + "home": "Strona główna", + "gallery": "Galeria", + "about": "O aplikacji", + "github": "GitHub" + }, + "homePage": { + "description": "Twórz i symuluj interaktywnie sceny optyki geometrycznej 2D.\nCałkowicie darmowa aplikacja webowa. Kod źródłowy jest [dostępny na GitHub](/github).", + "launchSimulator": "Uruchom symulator" + }, + "tools": { + "title": "Narzędzia", + "categories": { + "lightSource": "Źródło światła", + "mirror": "Zwierciadła", + "glass": "Szkła", + "blocker": "Przesłony", + "other": "Inne" + }, + "common": { + "clickInstruction": "Kliknij, aby utworzyć.", + "lineInstruction": "Przeciągnij lub kliknij, aby utworzyć.", + "circleInstruction": "Przeciągnij lub kliknij, aby utworzyć." + }, + "SingleRay": { + "title": "Promień", + "description": "Pojedynczy promień światła określony przez dwa punkty.", + "instruction": "Przeciągnij lub kliknij, aby utworzyć. Pierwszy punkt to źródło, wysyłające promień w kierunku drugiego punktu." + }, + "Beam": { + "title": "Wiązka", + "description": "Z odcinka wyłania się równoległa lub rozbieżna wiązka promieni o gęstości kontrolowanej przez suwak 'Gęstość promieni'." + }, + "PointSource": { + "title": "Źródło punktowe", + "description": "Promienie wychodzące z jednego punktu. Ich liczba regulowana jest za pomocą suwaka 'Gęstość promieni'." + }, + "AngleSource": { + "instruction": "Przeciągnij lub kliknij, aby utworzyć. Pierwszy punkt to źródło, wysyłające promień w kierunku drugiego punktu.", + "description": "Źródło punktowe o zadanym kącie emisji." + }, + "Mirror": { + "title": "Płaskie", + "description": "Symuluje odbicie światła w zwierciadle płaskim." + }, + "otherMirror": { + "title": "zakrzywione", + "description": "Zwierciadło, którego powierzchnia jest zakrzywiona. Może być kołowa, paraboliczna lub zdefiniowana przez niestandardowe równanie y = f(x)." + }, + "ArcMirror": { + "title": "Sferyczne", + "description": "Zwierciadło, którego powierzchnia w przekroju jest fragmentem okręgu, określonym za pomocą trzech punktów.", + "instruction": "Przeciągnij lub kliknij, aby utworzyć. Pierwsze 2 punkty określają odstęp między końcami łuku, ostatni punkt określa promień krzywizny." + }, + "ParabolicMirror": { + "title": "Paraboliczne", + "description": "Zwierciadło, którego powierzchnia w przekroju jest fragmentem paraboli, określonej za pomocą trzech punktów.", + "instruction": "Przeciągnij lub kliknij, aby utworzyć." + }, + "CustomMirror": { + "title": "Równanie niestandardowe", + "description": "Zwierciadło, którego kształt jest określony przez niestandardowe równanie y = f(x), gdzie (x,y) jest w przekształconych współrzędnych, w których dwoma punktami kontrolnymi są (-1,0) i (1,0)." + }, + "IdealMirror": { + "title": "Idealnie zakrzywione", + "description": "Idealnie 'zakrzywione' zwierciadło, dokładnie spełniające równanie (1/x + 1/y = 1/f). Ogniskową można ustawić bezpośrednio." + }, + "BeamSplitter": { + "title": "Rozdzielacz wiązki", + "description": "Zwierciadło odbijające pewien procent padającego światła." + }, + "PlaneGlass": { + "title": "Półpłaszczyzna", + "description": "Symuluje załamanie i odbicie światła na granicy ośrodków.", + "instruction": "Przeciągnij lub kliknij, aby utworzyć." + }, + "otherGlass": { + "title": "inne kształty", + "description": "Szkło o dowolnych kształtach, ograniczonych odcinkami i łukami okręgów lub zdefiniowanych układem nierówności f(x) < y < g(x)." + }, + "CircleGlass": { + "title": "Koło", + "description": "Szkło o przekroju kołowym, określonym przez środek i punkt na brzegu." + }, + "Glass": { + "title": "Dowolny kształt / Wielokąt", + "description": "Szkło o dowolnych kształtach, mających przekroje ograniczone odcinkami i fragmentami okręgów.", + "instruction": "Kliknij, aby utworzyć odcinek; przeciągnij, aby utworzyć łuk; kliknij punkt początkowy, żeby zakończyć rysowanie." + }, + "CustomGlass": { + "title": "Równanie niestandardowe", + "description": "Szkło o kształcie zdefiniowanym przez niestandardową nierówność f(x) < y < g(x), gdzie (x,y) jest w przekształconych współrzędnych, w których dwoma punktami kontrolnymi są (-1,0) i (1,0)." + }, + "IdealLens": { + "title": "Soczewka idealna", + "description": "Idealna soczewka, która spełnia dokładnie równanie (1/x + 1/y = 1/f). Ogniskową można ustawić bezpośrednio." + }, + "SphericalLens": { + "title": "Soczewka sferyczna", + "description": "Soczewka sferyczna." + }, + "CircleGrinGlass": { + "title": "Koło gradientowe", + "description": "Szkło z konfigurowaną funkcją współczynnika załamania n(x,y) i kołową krawędzią." + }, + "GrinGlass": { + "title": "Wielokąt gradientowy", + "description": "Szkło z konfigurowaną funkcją współczynnika załamania n(x,y) i wielokątną krawędzią.", + "instruction": "Kliknij, aby utworzyć odcinek, kliknij punkt początkowy po zakończeniu rysowania.", + "warning": "OSTRZEŻENIE: Obsługiwane są tylko proste wielokąty, w przeciwnym razie zachowanie jest nieprzewidywalne." + }, + "otherGrinGlass": { + "title": "Szkło gradientowe (GRIN)" + }, + "Blocker": { + "title": "Przesłona liniowa", + "description": "Przeszkoda - odcinek - pochłaniająca padające promienie." + }, + "CircleBlocker": { + "title": "Przesłona kołowa", + "description": "Przeszkoda - okrąg - pochłaniająca padające promienie." + }, + "Aperture": { + "title": "Apertura", + "description": "Para blokerów światła, które pochłaniają padające promienie. Rozmiar otworu można regulować symetrycznie.", + "instruction": "Przeciągnij lub kliknij dwa punkty końcowe, aby utworzyć." + }, + "Ruler": { + "title": "Linijka", + "description": "Linijka odmierzająca odległość od punktu zero (pierwsze kliknięcie) do innego punktu (drugie kliknięcie)." + }, + "Protractor": { + "title": "Kątomierz", + "description": "Kątomierz określony przez środek (wierzchołek kąta - pierwsze kliknięcie) i inny punkt dla kierunku zerowego (drugie kliknięcie). Skala jest w stopniach." + }, + "Detector": { + "title": "Detektor", + "description": "Narzędzie do pomiaru szybkości przepływu energii (P), szybkości prostopadłego przepływu pędu (F⊥), i szybkości równoległego przepływu pędu (F∥) przez odcinek. . Jednostki są umowne." + }, + "TextLabel": { + "title": "Tekst", + "description": "Etykieta tekstowa." + }, + "LineArrow": { + "title": "Linia / Strzałka", + "description": "Odcinek lub strzałka." + }, + "Drawing": { + "title": "Rysunek", + "description": "Narzędzie do rysowania odręcznego.", + "instruction": "Przeciągnij, aby narysować." + }, + "moveView": { + "title": "Przesuń widok", + "description": "Przeciągnij, aby przesunąć widok. (Przeciąganie prawym przyciskiem myszy ma tę samą funkcję)." + } + }, + "view": { + "title": "Widok", + "rays": { + "title": "Promienie", + "description": "Pokaż promienie. Gdy 'Gęstość promieni' jest duża, wiązka pojawia się jako ciągła." + }, + "extended": { + "title": "Rozszerzone promienie", + "description": "Pokaż zarówno promienie, jak i ich przedłużenia. Kolor pomarańczowy wskazuje przedłużenia do tyłu, a szary do przodu.", + "simulateColorsNote": "Gdy opcja „Symuluj kolory” jest włączona, są one wyświetlane w kolorach źródłowych i zamiast tego wyróżniane linią przerywaną." + }, + "images": { + "title": "Wszystkie obrazy", + "description": "Pokaż położenie wszystkich obrazów. Żółte punkty oznaczają obrazy rzeczywiste, pomarańczowe obrazy pozorne, a szare (brak na tym zdjęciu) obiekty wirtualne. Zwróć uwagę, że niektórych obrazów nie można wykryć, jeśli 'Gęstość promieni' nie jest wystarczająco wysoka.", + "simulateColorsNote": "Gdy opcja „Symuluj kolory” jest włączona, są one wyświetlane w kolorach źródłowych i zamiast tego rozróżniane na podstawie wielkości kropek." + }, + "observer": { + "title": "Widziane przez obserwatora", + "description": "Symuluje promienie i obrazy widziane z określonego miejsca. Obserwatora symbolizuje niebieskie kółko. Wszelkie przecinające je promienie uważa się za 'obserwowane'. Obserwator nie wie, gdzie faktycznie zaczynają się promienie, ale będzie mu się wydawało, że zaczynają się w pewnym punkcie (punktach), jeśli się tam przecinają. Promienie są pokazane na niebiesko, a punkty na żółto (rzeczywiste) lub pomarańczowo (pozorne).", + "simulateColorsNote": "Gdy opcja „Symuluj kolory” jest włączona, zamiast tego są one wyświetlane w kolorach źródłowych.", + "instruction": "Przeciągnij dużą niebieską kropkę, aby przesunąć obserwatora." + } + }, + "simulateColors": { + "title": "Symuluj kolory", + "description": "Symulacja kolorów (długości fal) źródeł światła, mieszania kolorów, filtrowania kolorów przez filtry blokujące i lustra oraz dyspersji chromatycznej szkieł.", + "instruction": "Po wybraniu można ustawić te parametry dla tych obiektów. Aby symulować widma kolorów, należy nałożyć na siebie promienie o różnych długościach fal.", + "warning": "Kolory wyświetlane na ekranie są jedynie przybliżone i mogą być bardzo niedokładne, gdy 'Gęstość promieni' jest zbyt wysoka lub zbyt niska." + }, + "languageDropdown": { + "title": "Język: {{language}}", + "translatedFraction": "{{fraction}} przetłumaczone" + } +} \ No newline at end of file diff --git a/locales/pl/simulator.json b/locales/pl/simulator.json new file mode 100644 index 00000000..fe0c8b25 --- /dev/null +++ b/locales/pl/simulator.json @@ -0,0 +1,181 @@ +{ + "welcome": { + "title": "Witamy w symulacji promieni optycznych", + "instruction": "Aby dodać komponent optyczny, zaznacz narzędzie i kliknij puste miejsce.\nAby załadować przykład, [przejdź do strony Galerii](/gallery)." + }, + "common": { + "saveButton": "Zapisz", + "cancelButton": "Anuluj", + "closeButton": "Zamknij" + }, + "file": { + "title": "Plik", + "undo": { + "title": "Cofnij" + }, + "redo": { + "title": "Ponów" + }, + "reset": { + "title": "Resetuj" + }, + "save": { + "title": "Zapisz" + }, + "open": { + "title": "Otwórz", + "description": "Otwórz istniejący plik lub obraz tła. Obraz tła zostanie wyświetlony z punktu początkowego współrzędnych. (Lub upuść plik)" + }, + "viewGallery": { + "title": "Zobacz Galerię", + "description": "Przejdź do strony Galerii, aby załadować przykład." + } + }, + "settings": { + "title": "Ustawienia", + "more": "Więcej", + "rayDensity": { + "title": "Gęstość promieni", + "description": "Określa liczbę promieni emitowanych przez belki i źródła punktowe. Ma to również wpływ na dokładność wykrywania obrazu i renderowania kolorów." + }, + "layoutAids": { + "title": "Opcje układu", + "showGrid": "Siatka", + "snapToGrid": "Przyciągaj do siatki", + "lockObjs": "Zablokuj obiekty" + }, + "zoom": { + "title": "Zoom" + }, + "language": { + "title": "Język" + }, + "showHelpPopups": { + "title": "Pokaż okienka pomocy", + "description": "Określa, czy wyświetlać wyskakujące okienka pomocy po najechaniu kursorem na przyciski. (Załaduj ponownie stronę, aby zastosować.)" + }, + "advancedHelp": "Aby uzyskać zaawansowaną pomoc, zobacz ikonę pomocy w prawym dolnym rogu." + }, + "objBar": { + "showAdvanced": { + "title": "Więcej opcji..." + }, + "applyToAll": { + "title": "Zastosuj do wszystkich" + }, + "duplicate": { + "title": "Powiel" + }, + "delete": { + "title": "Usuń" + }, + "unselect": { + "title": "Odznacz", + "description": "Usuń zaznaczenie tego obiektu (kliknięcie prawym przyciskiem myszy pustego miejsca ma tę samą funkcję)." + } + }, + "sceneObjs": { + "common": { + "brightness": "Jasność", + "brightnessInfo": { + "rayDensity": "Efektywne tylko wtedy, gdy 'Gęstość promieni' jest wystarczająco wysoka.", + "rayDensitySlider": "Aby kontrolować liczbę emitowanych promieni, dostosuj ogólny suwak 'Gęstość promieni'." + }, + "wavelength": "Długość fali", + "emisAngle": "Kąt emisji", + "random": "Losowo", + "lambert": "Lambertowskie", + "focalLength": "Ogniskowa" + }, + "Beam": { + "imageDetectionWarning": "Wykrywanie obrazu może nie działać w przypadku wiązek rozbieżnych/losowych." + }, + "AngleSource": { + "symmetric": "Symetryczna" + }, + "BaseFilter": { + "filter": "Filtr", + "bandwidth": "Szerokość pasma", + "invert": "Odwróć" + }, + "IdealMirror": { + "cartesianSign": "Konwencja znaków" + }, + "BeamSplitter": { + "transRatio": "Współczynnik transmisji" + }, + "BaseGlass": { + "refIndex": "Współczynnik załamania", + "refIndexInfo": { + "relative": "względny, jeśli znajduje się w innym szkle", + "effective": "Jeśli ten obiekt ma być symulowany z bezwzględnym współczynnikiem załamania światła n₁, ale jest umieszczony wewnątrz innego szkła o współczynniku załamania światła n₀, to należy tutaj ustawić współczynnik załamania światła na n₁/n₀. W bardziej skomplikowanych przypadkach, gdy kilka obiektów szklanych nakłada się na siebie, efektywny współczynnik odbicia tego obszaru jest równy iloczynowi współczynników odbicia poszczególnych szkieł." + }, + "cauchyCoeff": "Współczynnik Cauchy'ego" + }, + "BaseGrinGlass": { + "refIndexFnOrigin": "Początek układu n(x,y)", + "stepSize": "Rozmiar kroku rozwiązywania numerycznego", + "stepSizeInfo": "Wielkość kroku metody Eulera do rozwiązywania równania eikonału promienia - więcej informacji można znaleźć w funkcji 'step' i dokumentacji w pliku 'BaseGrinGlass.js'.", + "intersectTol": "Tolerancja intersekcji", + "symbolicBodyMerging": "Symboliczne łączenie ciał", + "symbolicBodyMergingInfo": { + "all": "Ten przełącznik dotyczy wszystkich obiektów GRIN w symulacji.", + "impl": "Ten symulator ma obecnie dwie implementacje propagacji światła między różnymi ośrodkami dla obiektów GRIN - numeryczną i symboliczną (patrz funkcje 'multRefIndex' i 'devRefIndex' w 'BaseGrinGlass.js').", + "implNote": "Implementacja numeryczna jest szybsza, ale nie zawsze działa poprawnie (w zależności od konkretnego przypadku) w scenariuszach, gdy jest używana z więcej niż jednym obiektem GRIN, takim, że przynajmniej jeden z nich ma funkcję współczynnika załamania światła, która nie jest zdefiniowana w całej płaszczyźnie, podczas gdy implementacja symboliczna jest wolniejsza, ale odporna na takie problemy." + } + }, + "CircleGrinGlass": { + "epsInfo": { + "units": "Jednostki - [długość]^2.", + "functions": "Ta tolerancja numeryczna jest używana w funkcjach 'isOutsideGlass', 'isInsideGlass' i 'isOnBoundary' w pliku 'CircleGrinGlass.js'." + } + }, + "GrinGlass": { + "epsInfo": { + "units": "Jednostki - [długość].", + "functions": "Ta tolerancja numeryczna jest używana w funkcjach 'isOnBoundary' i 'countIntersections' w pliku 'GrinGlass.js'." + } + }, + "Aperature": { + "diameter": "Średnica" + }, + "Detector": { + "irradMap": "Mapa irradiancji", + "binSize": "Rozmiar pojemnika", + "exportData": "Eksportuj dane" + }, + "TextLabel": { + "fontSize": "Rozmiar czcionki", + "font": "Czcionka", + "fontStyle": "Styl", + "alignment": "Wyrównanie", + "smallCaps": "Małe litery", + "angle": "Kąt" + }, + "LineArrow": { + "arrow": "Strzałka do przodu", + "backArrow": "Strzałka do tyłu" + }, + "Drawing": { + "finishDrawing": "Zakończ rysowanie" + }, + "CropBox": { + "svgWarning": "Eksportuj do SVG. Mieszanki kolorów i względne współczynniki załamania światła poniżej 1 nie są obsługiwane." + } + }, + "saveModal": { + "title": "Zapisz", + "fileName": "Nazwa" + }, + "languageModal": { + "title": "Język", + "translatedFraction": "przetłumaczone", + "helpTranslate": "Pomóż nam przetłumaczyć tę aplikację" + }, + "generalWarnings": { + "shareLinkTooLong": "Adres URL jest zbyt długi i może nie działać na niektórych platformach. Może być konieczne użycie \"Zapisz\" i zamiast tego udostępnienie pliku." + }, + "footer": { + "processing": "Przetwarzanie... Kliknij tutaj, aby zatrzymać." + } +} \ No newline at end of file diff --git a/locales/pt-BR.json b/locales/pt-BR.json deleted file mode 100644 index 3b89015c..00000000 --- a/locales/pt-BR.json +++ /dev/null @@ -1,863 +0,0 @@ -{ - "appName": { - "message": "Simulador - Simulação de Óptica de Raios" - }, - "appShortName": { - "message": "Óptica de Raios" - }, - "appDesc": { - "message": "Uma aplicação web grátis e de código aberto para criação e simulação de cenas de óptica geométrica 2D." - }, - "homepage_desc": { - "message": "Crie e simule cenas ópticas geométricas 2D interativamente.
Totalmente gratuito e baseado na web. Código-fonte está disponível no GitHub." - }, - "launch_simulator": { - "message": "Abrir Simulador" - }, - "home": { - "message": "Início" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/pt-BR/" - }, - "gallery": { - "message": "Galeria" - }, - "gallery_url": { - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "message": "Bem-vindo à Simulação de Óptica de Raios
Para adicionar um componente ótico, selecione uma ferramenta e clique no espaço vazio.
Para carregar um exemplo, por favor visite a página da Galeria." - }, - "loading_msg": { - "message": "Bem-vindo à Simulação de Óptica de Raios
Carregando cena a partir de URL... Por favor aguarde." - }, - "toolbar_title": { - "message": "Ferramenta: " - }, - "toolname_SingleRay": { - "message": "Raio único" - }, - "toolname_AngleSource": { - "message": "Fonte pontual" - }, - "toolname_PointSource": { - "message": "Fonte pontual" - }, - "toolname_Beam": { - "message": "Feixe" - }, - "toolname_mirror_": { - "message": "Espelho" - }, - "toolname_Mirror": { - "message": "Espelho" - }, - "toolname_ArcMirror": { - "message": "Espelho" - }, - "toolname_ParabolicMirror": { - "message": "Espelho" - }, - "toolname_CustomMirror": { - "message": "Espelho" - }, - "toolname_IdealMirror": { - "message": "Espelho curvo ideal" - }, - "toolname_glass_": { - "message": "Vidro" - }, - "toolname_blocker_": { - "message": "Bloqueador" - }, - "toolname_BeamSplitter": { - "message": "Divisor de Feixe" - }, - "toolname_PlaneGlass": { - "message": "Vidro" - }, - "toolname_CircleGlass": { - "message": "Vidro" - }, - "toolname_CircleGrinGlass": { - "message": "Círculo com gradiente de índice" - }, - "toolname_Glass": { - "message": "Polígono / Arcos Circulares" - }, - "toolname_GrinGlass": { - "message": "Polígono com gradiente de índice" - }, - "toolname_IdealLens": { - "message": "Lente ideal" - }, - "toolname_SphericalLens": { - "message": "Lente esférica" - }, - "toolname_CustomGlass": { - "message": "Vidro" - }, - "toolname_Blocker": { - "message": "Bloqueador reto" - }, - "toolname_Aperture": { - "message": "Abertura" - }, - "toolname_CircleBlocker": { - "message": "Bloqueador circular" - }, - "toolname_DiffractionGrating": { - "message": "Grade de difraçãoBeta" - }, - "toolname_Ruler": { - "message": "Régua" - }, - "toolname_Protractor": { - "message": "Transferidor" - }, - "tool_Detector": { - "message": "Detector" - }, - "toolname_Detector": { - "message": "Detector" - }, - "toolname_TextLabel": { - "message": "Texto" - }, - "toolname_LineArrow": { - "message": "Linha" - }, - "toolname_Drawing": { - "message": "Desenho" - }, - "toolname_Handle": { - "message": "Ponto de manuseio" - }, - "toolname_CropBox": { - "message": "Exportar" - }, - "toolname_ModuleObj": { - "message": "MóduloBeta" - }, - "tool_more_": { - "message": "Outros" - }, - "toolname_": { - "message": "Mover vista" - }, - "modebar_title": { - "message": "Ver:" - }, - "modename_light": { - "message": "Raios" - }, - "modename_extended_light": { - "message": "Raios extendidos" - }, - "modename_images": { - "message": "Todas Imagens" - }, - "modename_observer": { - "message": "Visto por Observador" - }, - "simulateColors": { - "message": "Simular Cores" - }, - "File: ": { - "message": "Arquivo" - }, - "Tools: ": { - "message": "Ferramentas" - }, - "tool_SingleRay": { - "message": "Raio único" - }, - "tool_Beam": { - "message": "Feixe paralelo" - }, - "tool_PointSource": { - "message": "Fonte pontual (360°)" - }, - "tool_AngleSource": { - "message": "Fonte pontual (<360°)" - }, - "tool_PointSource_": { - "message": "Fonte pontual" - }, - "tool_lightSource_": { - "message": "Fonte de luz" - }, - "tool_mirror_": { - "message": "Espelho" - }, - "tool_Mirror": { - "message": "Segmento" - }, - "tool_ArcMirror": { - "message": "Arco Circular" - }, - "tool_ParabolicMirror": { - "message": "Parabólico" - }, - "tool_CustomMirror": { - "message": "Equação Personalizada" - }, - "tool_BeamSplitter": { - "message": "Divisor de Feixe" - }, - "tool_IdealMirror": { - "message": "Curvo Ideal" - }, - "tool_glass_": { - "message": "Vidro" - }, - "tool_blocker_": { - "message": "Bloqueador" - }, - "tool_PlaneGlass": { - "message": "Semi-plano" - }, - "tool_CircleGlass": { - "message": "Círculo" - }, - "tool_CircleGrinGlass": { - "message": "Círculo" - }, - "tool_Glass": { - "message": "Forma livre" - }, - "tool_GrinGlass": { - "message": "Forma livre" - }, - "tool_IdealLens": { - "message": "Lente Ideal" - }, - "tool_SphericalLens": { - "message": "Lente Esférica" - }, - "tool_CustomGlass": { - "message": "Equação Personalizada" - }, - "tool_Blocker": { - "message": "Bloqueador Reto" - }, - "tool_Aperture": { - "message": "Abertura" - }, - "tool_CircleBlocker": { - "message": "Bloqueador Circular" - }, - "tool_DiffractionGrating": { - "message": "Grade de DifraçãoBeta" - }, - "tool_Ruler": { - "message": "Régua" - }, - "tool_Protractor": { - "message": "Transferidor" - }, - "tool_TextLabel": { - "message": "Texto" - }, - "tool_LineArrow": { - "message": "Linha / Seta" - }, - "tool_Drawing": { - "message": "Desenhar" - }, - "tool_": { - "message": "Mover Vista" - }, - "View: ": { - "message": "Ver" - }, - "Settings: ": { - "message": "Configurações" - }, - "moresettings": { - "message": "Mais" - }, - "mode_rays": { - "message": "Raios" - }, - "mode_extended": { - "message": "Raios extendidos" - }, - "mode_images": { - "message": "Todas Imagens" - }, - "mode_observer": { - "message": "Visto por Observador" - }, - "zoom": { - "message": "Zoom" - }, - "help": { - "message": "Ajuda" - }, - "rayDensity": { - "message": "Densidade de Raios" - }, - "raydensity": { - "message": "Densidade de Raios:" - }, - "undo": { - "message": "Desfazer" - }, - "redo": { - "message": "Refazer" - }, - "reset": { - "message": "Reiniciar" - }, - "save": { - "message": "Salvar" - }, - "rename": { - "message": "Renomear" - }, - "get_link": { - "message": "Copiar Link Compartilhável" - }, - "export_svg": { - "message": "Exportar como PNG/SVG" - }, - "view_gallery": { - "message": "Ver Galeria" - }, - "save_name": { - "message": "Nome" - }, - "save_cancel": { - "message": "Cancelar" - }, - "save_description": { - "message": "
  • Você pode usar Configurações -> Sincronizar URL automaticamente ao invés de salvar para um arquivo.
  • Clique \"Renomear\" para mudar o título sem salvar um arquivo.
  • Você pode considerar contribuir um novo item para a Galeria.
" - }, - "open": { - "message": "Abrir" - }, - "layoutaids": { - "message": "Auxílio de posicionamento" - }, - "lockObjs": { - "message": "Travar Objetos" - }, - "showGrid": { - "message": "Grade" - }, - "snapToGrid": { - "message": "Ajustar na grade" - }, - "snaptogrid": { - "message": "Ajustar na grade" - }, - "length_unit_popover": { - "message": "A unidade de comprimento utilizada nesse simulador (exceto comprimentos de onda) é arbitrária e pode ser interpretada como qualquer unidade física (ex.: milímetros) contanto que seja dentro da simulação. Se aunidade parecer pequena ou grande demais, por favor, ajuste Configurações -> Escala de Comprimento." - }, - "lengthScale": { - "message": "Escala de ComprimentoBeta" - }, - "lengthScale_popover": { - "message": "Se a unidade padrão de comprimento estiver pequena demais ou grande demais para modelar um sistema físico quando interpretado como uma unidade física comum unit (ex.: milímetros), esse fator pode ser usado para alterar a escala da aparência (ex.: larguras de linha) na cena." - }, - "brightness": { - "message": "Brilho" - }, - "wavelength": { - "message": "Comprimento de onda (nm)" - }, - "dichroic": { - "message": "Dicróico" - }, - "filter": { - "message": "Filtro" - }, - "bandwidth": { - "message": "Largura de banda (nm)" - }, - "invert": { - "message": "Inverter" - }, - "emisAngle": { - "message": "Ângulo de Emissão (°)" - }, - "mirrored": { - "message": "Espelhado" - }, - "lineDensity": { - "message": "Linhas/mm" - }, - "slitRatio": { - "message": "Largura de vão / Espaçamento de linha" - }, - "customBrightness": { - "message": "Brilho Personalizado" - }, - "customBrightness_note_popover": { - "message": "Quando ligado, os brilhos dos raios difratados são personalizados por uma lista de números correspndendo a m = 0, 1, -1, 2, -2, .... O número será normalizado ao brilho do raio incidente. Os valores não na lista são definidos como 0. Por exemplo, \"1, 0.5, 0.5\" significa que o raio m=0 tem o mesmo brilho que o raio incidente, os raios m=1 e m=-1 têm metade do brilho, e todos os outros raios são ignorados." - }, - "symmetric": { - "message": "Simétrico" - }, - "eqn_note": { - "message": "
  • Constantes suportadas:
    pi e
  • Operadores suportados:
    + - * / ^
  • Funções suportadas:
    sqrt sin cos tan sec csc cot sinh cosh tanh log exp arcsin arccos arctan arcsinh arccosh arctanh floor round ceil trunc sgn max min abs
" - }, - "symbolic_grin": { - "message": "União simbólica de corpos" - }, - "grin_refractive_index": { - "message": "
  • Constantes suportadas:
    pi e
  • Operadores suportados:
    + - * / ^
  • Funções suportadas:
    sqrt sin cos tan sec csc cot sinh cosh tanh log arcsin arccos arctan
  • To simulate chromatic dispersion, use parameter lambda for the vacuum wavelength in nanometers.Beta
  • Somente suporta funções diferenciáveis.
  • A origem de n(x,y) está em coordenadas absolutas e n~~ao move com o objeto. Você pode clicar duas vezes em um ponto de controle para inspecionar suas coordenadas absolutas.
  • Para simulação mais precisa, veja \"Mais opções...\"
" - }, - "symbolic_grin_note_popover": { - "message": "

Esta opção se aplica a todos objetos GRIN na simulação.

Este simulador atualmente possi duas implementações de propagação de luz entre meios diferentes, para objetos GRIN - numérica e simbólica (ver funções 'multRefIndex' e 'devRefIndex' em 'CircleGrinGlass.js').

A implementação numérica é mais rápida mas nem sempre funciona corretamente (dependende do caso específico) em cenários quando é usada com mais de um objeto GRIN, tal que ao menos um deles possua uma função de índice refrativo que não é definida todo o plano, enquanto a implementação simbólica é mais lenta, mas robusta a esse tipo de problema.

" - }, - "focalLength": { - "message": "Comprimento focal" - }, - "cartesianSign": { - "message": "Convenção de Sinal Cartesiana" - }, - "refIndex": { - "message": "Índice refrativo*" - }, - "radii_of_curvature": { - "message": "Raios de curvatura" - }, - "focal_distances": { - "message": "Distâncias Focais" - }, - "refIndex_origin": { - "message": "Origem de n(x,y)" - }, - "stepSize": { - "message": "Tamanho de passo da solução numérica" - }, - "intersectTol": { - "message": "Tolerância de Interseção" - }, - "random": { - "message": "Aleatório" - }, - "lambert": { - "message": "Lambertiano" - }, - "diameter": { - "message": "Diâmetro" - }, - "irradMap": { - "message": "Mapa de Irradiância" - }, - "binSize": { - "message": "Tamanho do coletor" - }, - "scaleInterval": { - "message": "Intervalo da escala" - }, - "exportData": { - "message": "Exportar dados" - }, - "demodulize": { - "message": "Demodulizar" - }, - "fontSize": { - "message": "Tamanho da Fonte" - }, - "font": { - "message": "Fonte" - }, - "fontStyle": { - "message": "Estilo" - }, - "normal": { - "message": "Normal" - }, - "bold": { - "message": "Negrito" - }, - "italic": { - "message": "Itálico" - }, - "bolditalic": { - "message": "Negrito Itálico" - }, - "oblique": { - "message": "Oblíquo" - }, - "boldoblique": { - "message": "Negrito Oblíquo" - }, - "alignment": { - "message": "Alinhamento" - }, - "left": { - "message": "Esquerda" - }, - "center": { - "message": "Centro" - }, - "right": { - "message": "Direita" - }, - "text_here": { - "message": "Texto Aqui" - }, - "smallCaps": { - "message": "Maiúsculo pequeno" - }, - "angle": { - "message": "Ângulo (°)" - }, - "arrow": { - "message": "Seta frontal" - }, - "backArrow": { - "message": "Seta traseira" - }, - "stop_drawing": { - "message": "Finalizar Desenho" - }, - "cropBoxSize": { - "message": "Tamanho da Caixa de Corte" - }, - "format": { - "message": "Formato" - }, - "width": { - "message": "Largura" - }, - "rayCountLimit": { - "message": "Limite de quantidade de raios" - }, - "transformation": { - "message": "TransformaçãoBeta" - }, - "default": { - "message": "Padrão" - }, - "translation": { - "message": "Translação" - }, - "xTranslation": { - "message": "Translação X" - }, - "yTranslation": { - "message": "Translação Y" - }, - "rotation": { - "message": "Rotação" - }, - "scaling": { - "message": "Escala" - }, - "beam_warning": { - "message": "Detecção de imagem pode não funcionar com raios aleatórios/divergentes." - }, - "image_detection_warning": { - "message": "Esta ferramenta não suporta detecção de imagem." - }, - "non_simulateColors_warning": { - "message": "Esta ferramenta só funciona quando \"Simular Cores\" está ligado." - }, - "brightness_note_popover": { - "message": "

Somente faz efeito quando 'Densidade de Raios' está alta o suficiente.

Para controlar o número de raios emitidos, por favor ajuste o controle global de 'Densidade de Raios'.

" - }, - "refIndex_note_popover": { - "message": "

*Relativo se dentro de outro vidro

Se este objeto deve ser simulado com índice refrativo absoluto n₁, mas estiver dentro de outro vidro de índice refrativo n₀, então você deve definir o índice refrativo como n₁/n₀ aqui. Em casos mais complicados que vários vidros se sobreponham, o índice refrativo efetivo da região sobreposta é igual ao produto dos índices refrativos individuais.

" - }, - "stepSize_note_popover": { - "message": "

Tamanho de passo do método de Euler para resolver a equação do eikonal de raios - ver função 'step' e documentação dentro do arquivo 'CircleGrinGlass.js', para mais informações.

" - }, - "eps_CircleGrinGlass_note_popover": { - "message": "

Units - [length]^2.

Essa tolerância numérica é usada nas funções 'isOutsideGlass', 'isInsideGlass' e 'isOnBoundary', dentro do arquivo 'CircleGrinGlass.js'.

" - }, - "eps_GrinGlass_note_popover": { - "message": "

Units - [length].

Essa tolerância numérica é usada nas funções 'isOnBoundary' e 'countIntersections', dentro do arquivo'GrinGlass.js'.

" - }, - "cauchyCoeff": { - "message": "Coeficiente de Cauchy" - }, - "transRatio": { - "message": "Razão de Transmissão" - }, - "applytoall": { - "message": "Aplicar em Todos" - }, - "duplicate": { - "message": "Duplicar" - }, - "delete": { - "message": "Apagar" - }, - "unselect": { - "message": "Desselecionar" - }, - "unselect_popover": { - "message": "Desselecionar esse objeto (Botão direito do mouse em espaço vazio tem a mesma função.)" - }, - "showadvanced": { - "message": "Mais opções..." - }, - "processing": { - "message": "Processando... Clique aqui para parar." - }, - "contribute": { - "message": "Contribuir" - }, - "github": { - "message": "GitHub" - }, - "about": { - "message": "Sobre" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "message": "Ajude-nos a traduzir este aplicativo" - }, - "translated": { - "message": "traduzido" - }, - "undo_popover": { - "message": "Desfazer última ação. (Ctrl+Z)" - }, - "redo_popover": { - "message": "Refazer última ação. (Ctrl+Y)" - }, - "reset_popover": { - "message": "Desfazer todas as mudanças." - }, - "save_popover": { - "message": "Salvar a cena atual como um arquivo." - }, - "open_popover": { - "message": "Abrir um arquivo existente ou imagem de fundo. A imagem de fundo será exibida a partir origem das coordenadas. (Ou solte o arquivo)" - }, - "get_link_popover": { - "message": "Copiar e ir para a URL direta da cena atual, que pode ser utilizada para compartilhamento(possivelmente via encurtador de URL). Também veja Configurações -> Sincronização automática de URL." - }, - "get_link_warning": { - "message": "Talvez a URL seja comprida demais para funcionar em algumas plataformas. Você pode precisar de usar \"Salvar\" e compartilhar o arquivo ao invés disso." - }, - "export_svg_warning": { - "message": "Exportar como SVG: Misturas de cores e índices refrativos relativos abaixo de 1 não são suportados." - }, - "export_ray_count_warning": { - "message": "O número atual de raios na cena é maior que o limite de número de raios. Você pode precisar de aumentar o limite nas opções da Caixa de Corte." - }, - "view_gallery_popover": { - "message": "Ir para a página web da Galeria para carregar um exemplo." - }, - "tool_SingleRay_popover": { - "message": "Um único raio de luz definido por dois pontos. (Arraste ou clique para criar. O primeiro ponto é a fonte, disparando rumo ao segundo ponto.)" - }, - "tool_Beam_popover": { - "message": "Um feixe paralelo ou divergente de luz emerge de um segmento de linha, com densidade controlada pelo controle deslizante 'Densidade de raios'. (Arraste ou clique para criar.)" - }, - "tool_PointSource_popover": { - "message": "Raios emergem de um ponto único, com quantidade controlada pelo controle deslizante 'Densidade de raios'. (Clique para criar.)" - }, - "tool_AngleSource_popover": { - "message": "Fonte pontual com um ângulo de emissão definido." - }, - "tool_Mirror_popover": { - "message": "Simule a reflexão da luz em um espelho. (Arraste ou clique para criar.)" - }, - "tool_ArcMirror_popover": { - "message": "Um espelho cujo formato é parte de um círculo, que é definido por três pontos. (Arraste ou clique para criar. Os primeiros dois pontos definem o vão entre as bordas do arco, e o último ponto define o tamanho do arco.)" - }, - "tool_ParabolicMirror_popover": { - "message": "Um espelho cujo formato é uma parábola, que é definida por três pontos. (Arraste ou clique para criar.)" - }, - "tool_CustomMirror_popover": { - "message": "Um espelho cujo formato é definido por uma equação personalizada y = f(x), onde (x,y) está nas coordenadas transformadas em que os dois pontos de controle são (-1,0) and (1,0). (Arraste ou clique para criar.)" - }, - "tool_BeamSplitter_popover": { - "message": "Um espelho que transmite uma porcentagem da luz que chega (Arraste ou clique para criar.)" - }, - "tool_IdealMirror_popover": { - "message": "O espelho 'curvo' idealizado que obedece exatamente a equação (1/p + 1/q = 1/f). O comprimento focal pode ser definido diretamente. (Arraste ou clique para criar.)" - }, - "tool_PlaneGlass_popover": { - "message": "Simule a refração e a reflexão da luz em uma superfície. (Arraste ou clique para criar.)" - }, - "tool_CircleGlass_popover": { - "message": "Vidro com um formato circular, definido por seu centro e um ponto na superfície. (Arraste ou clique para criar.)" - }, - "tool_CircleGrinGlass_popover": { - "message": "Vidro com uma função personalizada de índice refrativo n(x,y) e um formato circular. (Arraste ou clique para criar.)" - }, - "tool_Glass_popover": { - "message": "Vidro com qualquer formato construído com segmentos de linha e arcos circulares. (Clique para criar um segmento, arraste para criar um arco, e clique no ponto de início quando acabar de desenhar.)" - }, - "tool_GrinGlass_popover": { - "message": "Vidro com uma função personalizada de índice refrativo n(x,y) e um formato poligonal. AVISO: Somente polígonos simples são suportados, senão o comportamento pode ser imprevisível. (Clique para criar um segmento, arraste para criar um arco, e clique no ponto de início quando acabar de desenhar.)" - }, - "tool_IdealLens_popover": { - "message": "Uma lente ideal que obedece exatamente à equação de lente fina (1/p + 1/q = 1/f). O comprimento focal pode ser definido diretamente. (Arraste ou clique para criar.)" - }, - "tool_SphericalLens_popover": { - "message": "Uma lente esférica. (Clique para criar.)" - }, - "tool_CustomGlass_popover": { - "message": "Vidro com o formato definido por uma inequalidade personalizada f(x) < y < g(x), onde (x,y) está nas coordenadas transformadas em que os pontos de controle são (-1,0) e (1,0). (Arraste ou clique para criar.)" - }, - "tool_Blocker_popover": { - "message": "Um segmento de linha bloqueador de luz que absorve os raios incidentes. (Arraste ou clique para criar.)" - }, - "tool_Aperture_popover": { - "message": "Um par de bloqueadores de luz que absorvem os raios incidentes. O tamanho do furo pode ser ajustado simetricamente. (Arraste ou clique nas duas pontas para criar.)" - }, - "tool_CircleBlocker_popover": { - "message": "Um bloqueador circular de luz que absorve os raios incidentes. (Arraste ou clique para criar.)" - }, - "tool_DiffractionGrating_popover": { - "message": "Uma grade de difração que divide luz em um ângulo dependente do comprimento de onda (Arraste ou clique para criar.)" - }, - "tool_Ruler_popover": { - "message": "Uma régua a partir de um ponto zero até um outro ponto. (Arraste ou clique para criar.)" - }, - "tool_Protractor_popover": { - "message": "Um transferidor definido a partir do centro e outro ponto para a direção do zero. A escala está em graus (Arraste ou clique para criar.)" - }, - "tool_Detector_popover": { - "message": "Uma ferramenta para medir a taxa de fluxo de energia (P), a taxa de fluxo de momento perpendicular (F⊥), e a taxa de fluxo de momento paralelo (F∥) através de um segmento de linha. (Arraste ou clique para criar o segmento de linha.) As unidades são arbitrárias." - }, - "tool_Detector_info_popover": { - "message": "
  • P: A taxa de fluxo de energia em B/s (ver abaixo).
  • F⊥: A taxa de fluxo de momento perpendicular em (B/s)/c.
  • F∥: A taxa de fluxo de momento paralelo em (B/s)/c.
  • A irradiância no CSV exportado está em (B/s)/L.
  • L é a unidade arbitrária de comprimento utilizada nesse simulador.
  • B é uma unidade arbitrária de fluxo radiante ou fluxo luminoso, correspondente à unidade da opção \"Brilho\" sendo B/L para raios não Lambertianos e 500B/360° para fontes pontuais.
  • O fator adimensional s é a \"Escala de Brilho\" exibida em Configurações -> Mostrar caixa de status, que é igual a 1 quando \"Densidade de Raios\" está acima de certo ponto e proporcional a \"Densidade de Raios\" caso contrário.
  • Se alguns raios forem truncados na série infinita de reflexão interna, a truncação total é exibida como estimativas de erro.
" - }, - "tool_TextLabel_popover": { - "message": "Um rótulo de texto." - }, - "tool_LineArrow_popover": { - "message": "Uma seta ou segmento de linha. (Arraste ou clique para criar.)" - }, - "tool_Drawing_popover": { - "message": "Uma ferramenta de desenho à mão livre. (Arraste para desenhar)" - }, - "tool__popover": { - "message": "Arraste para mover a vista. (Arrastar com o botão direito do mouse tem a mesma função.)" - }, - "mode_rays_popover": { - "message": "Exibir os raios. Quando a 'Densidade de Raios' está alta, eles parecem ser contínuos." - }, - "mode_extended_popover": { - "message": "Exibir tanto os raios quanto suas extensões. Laranja indica extensões para trás, e cinza indica para frente.
Quando 'Simular Cores' está ligado, eles são exibidos na cor fonte e distinguidos por traços." - }, - "mode_images_popover": { - "message": "Mostra a posição de todas imagens. Pontos amarelos indicam imagens reais, laranja indica imagens virtuais, e cinza (nenhuma nesta imagem) indica objetos virtuais. Note que algumas imagens não podem ser detectadas se 'Densidade de Raios' não estiver alta o suficiente.
Quando 'Simular Cores' está ligado, eles são exibidos nas cores fonte e distinguidos por tamanhos de ponto." - }, - "mode_observer_popover": { - "message": "Simule os raios e imagens vistos de uma posição. O círculo azul é o observador. Quaisquer raios atravessando ele são considerados 'Observados'. O observador não sabe onde os raios realmente começam, mas pode pensar que eles começam em algum ponto se eles intersecionam lá. Os raios são exibidos em azul, e os pontos em amarelo (real) ou laranja (virtual). (Arraste o ponto grande azul para mover o observador.)
Quando 'Simular Cores' está ligado, eles são exibidos nas cores fonte." - }, - "simulateColors_popover": { - "message": "Simular cores (comprimentos de onda) de fontes luminosas, mistura de cores, filtragem de cores por bloqueadores e espelhos, e dispersão cromática de vidros. Você pode definir esses parâmetros para esses objetos quando selecionados. Para simular espectros de cor, sobreponha raios com comprimentos de onda diferentes. As cores exibidas na tela são apenas aproximações, e podem ser muito imprecisas quando 'Densidade de Raios' está muito alta ou muito baixa." - }, - "rayDensity_popover": { - "message": "Determina o número de raios a serem emitidos por feixes e fontes pontuais. Isso também afeta a precisão da detecção de imagens e da reprodução de cores." - }, - "showGrid_popover": { - "message": "Define a visibilidade da grade de fundo." - }, - "grid_popover": { - "message": "Define se vai ajustar à grade." - }, - "lockObjs_popover": { - "message": "Define se os objetos podem ser movidos ou não." - }, - "zoom_popover": { - "message": "Configurar zoom com porcentagem." - }, - "help_popover": { - "message": "Arraste restrito

Enquanto arrasta um objeto, segure Shift para limitar ao sentido horizontal/vertical; segure Ctrl para clonar. Quando criando um objeto em formato de linha ou arrastando seus pontos finais, segure Shift para travar o ângulo ou ajustar para 0°, 45°, 90°; segure Ctrl para rotacionar/ajustar escala com relação a seu centro.

Agrupar, rotacionar e ajustar escala de objetos

Segure Ctrl, clique em vários pontos de controle, então clique em espaço vazio para agrupar esses pontos e criar um ponto de manuseio. Arraste o ponto de manuseio (ou use as setas do teclado) para mover o grupo; Shift+arraste para limitar a horizontal/vertical; Ctrl+arraste para rotacionar, Ctrl+Shift+arraste para ajustar escala. Arraste o \"+\" para definir o centro de rotação/escala. Clique no ponto de manuseio e aperte Ctrl+D para duplicar o grupo; aperte Delete para desagrupar.

Editar coordenadas diretamente

Clique duplo ou clique com botão direito no ponto de controle do objeto, edite as coordenadas (x,y), então aperte Enter.

Atalhos de teclado

Quando um objeto está selecionado (ao clicar nele), aperte as setas do teclado para movê-lo; Ctrl+D para duplicar; tecla Delete para apagar.

Contate-nos

O jeito sugerido é ir até Discussões ou Problemas no GitHub. Se você não usar o GitHub, pode nos mandar um email em ray-optics@phydemo.app (por favor use Inglês).

Contribuições diretas também são bem-vindas (ver o guia de contribuições).

" - }, - "show_help_popups": { - "message": "Exibir popups de ajuda" - }, - "show_help_popups_popover": { - "message": "Define se vai exibir popups de ajuda quando pairando sobre botões. (Recarregue a página para fazer efeito.)" - }, - "show_json_editor": { - "message": "Exibir editor JSONBeta" - }, - "show_json_editor_popover": { - "message": "Exibir o editor de código para a representação JSON da cena, que é necessária quando criando um módulo personalizado (Ver Ferramentas -> Outros -> Importar Módulos -> Criar módulos personalizados)." - }, - "show_status": { - "message": "Exibir caixa de status" - }, - "show_status_popover": { - "message": "Exibir a caixa de status, que inclui as coordenadas do mouse, informação de performance e o brilho truncado (o brilho total dos raios truncados na série infinita de reflexão interna)." - }, - "auto_sync_url": { - "message": "Sincronizar URL automaticamente" - }, - "auto_sync_url_popover": { - "message": "Quando habilitado, a URL será atualizada automaticamente com a cena atual, então você não precisa de ficar salvando a cena manualmente. Para definir o título, use Arquivo -> Salvar -> Renomear" - }, - "auto_sync_url_warning": { - "message": "A cena é grande demais para sincronizar com URL. Por favor, salve manualmente" - }, - "gridSize": { - "message": "Tamanho da Grade" - }, - "observer_size": { - "message": "Tamanho do Observador" - }, - "language": { - "message": "Linguagem" - }, - "close": { - "message": "Fechar" - }, - "advanced_help": { - "message": "Para ajuda avançada, veja o ícone de ajuda no canto inferior direito." - }, - "ray_count": { - "message": "Número de segmentos de raio: " - }, - "total_truncation": { - "message": "Brilho truncado: " - }, - "brightness_scale": { - "message": "Escala de Brilho: " - }, - "time_elapsed": { - "message": "Tempo decorrido (ms): " - }, - "force_stopped": { - "message": "Interrompido à força." - }, - "mouse_coordinates": { - "message": "Coordenadas do Mouse: " - }, - "modules_tutorial": { - "message": "Criar módulos personalizados" - }, - "modules_tutorial_url": { - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "message": "Há dois elementos ópticos idênticos na cena que se sobrepõem completamente." - }, - "import_modules": { - "message": "Importar Módulos..." - }, - "import_modules_title": { - "message": "Importar Módulos" - }, - "modules_url": { - "message": "../modules/modules.html" - }, - "remove_module": { - "message": "Remover módulo" - }, - "module_conflict": { - "message": "Outro módulo com o mesmo nome já existe na cena atual. Você pode colocar outro nome, ou deixá-lo igual para sobrepor o módulo existente." - }, - "brightness_inconsistent_warning": { - "message": "O brilho de duas ou mais fontes de luz satura com razões inconsistentes. Isso pode levar a erros nas leituras do detector e reprodução de cores. Por favor aumente a densidade de raios ou reduza os brilhos das fontes luminosas." - } -} \ No newline at end of file diff --git a/locales/pt-BR/main.json b/locales/pt-BR/main.json new file mode 100644 index 00000000..99a86e63 --- /dev/null +++ b/locales/pt-BR/main.json @@ -0,0 +1,212 @@ +{ + "meta": { + "languageName": "Português (Brasil)", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "Simulação de Óptica de Raios", + "shortName": "Óptica de Raios", + "description": "Uma aplicação web grátis e de código aberto para criação e simulação de cenas de óptica geométrica 2D." + }, + "pages": { + "simulator": "Simulador", + "home": "Início", + "gallery": "Galeria", + "about": "Sobre", + "github": "GitHub" + }, + "homePage": { + "description": "Crie e simule cenas ópticas geométricas 2D interativamente.\nTotalmente gratuito e baseado na web. Código-fonte está [disponível no GitHub](/github).", + "launchSimulator": "Abrir Simulador" + }, + "tools": { + "title": "Ferramentas", + "categories": { + "lightSource": "Fonte de luz", + "mirror": "Espelho", + "glass": "Vidro", + "blocker": "Bloqueador", + "other": "Outros" + }, + "common": { + "clickInstruction": "Clique para criar.", + "lineInstruction": "Arraste ou clique para criar.", + "circleInstruction": "Arraste ou clique para criar." + }, + "SingleRay": { + "title": "Raio único", + "description": "Um único raio de luz definido por dois pontos.", + "instruction": "Arraste ou clique para criar. O primeiro ponto é a fonte, disparando rumo ao segundo ponto." + }, + "Beam": { + "title": "Feixe paralelo", + "description": "Um feixe paralelo ou divergente de luz emerge de um segmento de linha, com densidade controlada pelo controle deslizante 'Densidade de raios'." + }, + "PointSource": { + "title": "Fonte pontual", + "description": "Raios emergem de um ponto único, com quantidade controlada pelo controle deslizante 'Densidade de raios'." + }, + "AngleSource": { + "instruction": "Arraste ou clique para criar. O primeiro ponto é a fonte, disparando rumo ao segundo ponto.", + "description": "Fonte pontual com um ângulo de emissão definido." + }, + "Mirror": { + "title": "Segmento", + "description": "Simule a reflexão da luz em um espelho." + }, + "otherMirror": { + "title": "Equação Personalizada", + "description": "Um espelho cujo formato é definido por uma equação personalizada y = f(x), onde (x,y) está nas coordenadas transformadas em que os dois pontos de controle são (-1,0) and (1,0)." + }, + "ArcMirror": { + "title": "Arco Circular", + "description": "Um espelho cujo formato é parte de um círculo, que é definido por três pontos.", + "instruction": "Arraste ou clique para criar. Os primeiros dois pontos definem o vão entre as bordas do arco, e o último ponto define o tamanho do arco." + }, + "ParabolicMirror": { + "title": "Parabólico", + "description": "Um espelho cujo formato é uma parábola, que é definida por três pontos.", + "instruction": "Arraste ou clique para criar." + }, + "CustomMirror": { + "title": "Equação Personalizada", + "description": "Um espelho cujo formato é definido por uma equação personalizada y = f(x), onde (x,y) está nas coordenadas transformadas em que os dois pontos de controle são (-1,0) and (1,0)." + }, + "IdealMirror": { + "title": "Curvo Ideal", + "description": "O espelho 'curvo' idealizado que obedece exatamente a equação (1/p + 1/q = 1/f). O comprimento focal pode ser definido diretamente." + }, + "BeamSplitter": { + "title": "Divisor de Feixe", + "description": "Um espelho que transmite uma porcentagem da luz que chega" + }, + "PlaneGlass": { + "title": "Semi-plano", + "description": "Simule a refração e a reflexão da luz em uma superfície.", + "instruction": "Arraste ou clique para criar." + }, + "otherGlass": { + "title": "Equação Personalizada", + "description": "Vidro com o formato definido por uma inequalidade personalizada f(x) < y < g(x), onde (x,y) está nas coordenadas transformadas em que os pontos de controle são (-1,0) e (1,0)." + }, + "CircleGlass": { + "title": "Círculo", + "description": "Vidro com um formato circular, definido por seu centro e um ponto na superfície." + }, + "Glass": { + "title": "Forma livre", + "description": "Vidro com qualquer formato construído com segmentos de linha e arcos circulares.", + "instruction": "Clique para criar um segmento, arraste para criar um arco, e clique no ponto de início quando acabar de desenhar." + }, + "CustomGlass": { + "title": "Equação Personalizada", + "description": "Vidro com o formato definido por uma inequalidade personalizada f(x) < y < g(x), onde (x,y) está nas coordenadas transformadas em que os pontos de controle são (-1,0) e (1,0)." + }, + "IdealLens": { + "title": "Lente Ideal", + "description": "Uma lente ideal que obedece exatamente à equação de lente fina (1/p + 1/q = 1/f). O comprimento focal pode ser definido diretamente." + }, + "SphericalLens": { + "title": "Lente Esférica", + "description": "Uma lente esférica." + }, + "CircleGrinGlass": { + "title": "Círculo", + "description": "Vidro com uma função personalizada de índice refrativo n(x,y) e um formato circular." + }, + "GrinGlass": { + "title": "Forma livre", + "description": "Vidro com uma função personalizada de índice refrativo n(x,y) e um formato poligonal.", + "instruction": "Clique para criar um segmento, arraste para criar um arco, e clique no ponto de início quando acabar de desenhar.", + "warning": "AVISO: Somente polígonos simples são suportados, senão o comportamento pode ser imprevisível." + }, + "otherGrinGlass": { + "title": "Polígono com gradiente de índice" + }, + "Blocker": { + "title": "Bloqueador Reto", + "description": "Um segmento de linha bloqueador de luz que absorve os raios incidentes." + }, + "CircleBlocker": { + "title": "Bloqueador Circular", + "description": "Um bloqueador circular de luz que absorve os raios incidentes." + }, + "Aperture": { + "title": "Abertura", + "description": "Um par de bloqueadores de luz que absorvem os raios incidentes. O tamanho do furo pode ser ajustado simetricamente.", + "instruction": "Arraste ou clique nas duas pontas para criar." + }, + "DiffractionGrating": { + "title": "Grade de Difração", + "description": "Uma grade de difração que divide luz em um ângulo dependente do comprimento de onda" + }, + "Ruler": { + "title": "Régua", + "description": "Uma régua a partir de um ponto zero até um outro ponto." + }, + "Protractor": { + "title": "Transferidor", + "description": "Um transferidor definido a partir do centro e outro ponto para a direção do zero. A escala está em graus" + }, + "Detector": { + "title": "Detector", + "description": "Uma ferramenta para medir a taxa de fluxo de energia (P), a taxa de fluxo de momento perpendicular (F⊥), e a taxa de fluxo de momento paralelo (F∥) através de um segmento de linha. As unidades são arbitrárias." + }, + "TextLabel": { + "title": "Texto", + "description": "Um rótulo de texto." + }, + "LineArrow": { + "title": "Linha / Seta", + "description": "Uma seta ou segmento de linha." + }, + "Drawing": { + "title": "Desenhar", + "description": "Uma ferramenta de desenho à mão livre.", + "instruction": "Arraste para desenhar" + }, + "moveView": { + "title": "Mover Vista", + "description": "Arraste para mover a vista. (Arrastar com o botão direito do mouse tem a mesma função.)" + }, + "modules": { + "import": "Importar Módulos...", + "remove": "Remover módulo" + } + }, + "view": { + "title": "Ver", + "rays": { + "title": "Raios", + "description": "Exibir os raios. Quando a 'Densidade de Raios' está alta, eles parecem ser contínuos." + }, + "extended": { + "title": "Raios extendidos", + "description": "Exibir tanto os raios quanto suas extensões. Laranja indica extensões para trás, e cinza indica para frente.", + "simulateColorsNote": "Quando 'Simular Cores' está ligado, eles são exibidos na cor fonte e distinguidos por traços." + }, + "images": { + "title": "Todas Imagens", + "description": "Mostra a posição de todas imagens. Pontos amarelos indicam imagens reais, laranja indica imagens virtuais, e cinza (nenhuma nesta imagem) indica objetos virtuais. Note que algumas imagens não podem ser detectadas se 'Densidade de Raios' não estiver alta o suficiente.", + "simulateColorsNote": "Quando 'Simular Cores' está ligado, eles são exibidos nas cores fonte e distinguidos por tamanhos de ponto." + }, + "observer": { + "title": "Visto por Observador", + "description": "Simule os raios e imagens vistos de uma posição. O círculo azul é o observador. Quaisquer raios atravessando ele são considerados 'Observados'. O observador não sabe onde os raios realmente começam, mas pode pensar que eles começam em algum ponto se eles intersecionam lá. Os raios são exibidos em azul, e os pontos em amarelo (real) ou laranja (virtual).", + "simulateColorsNote": "Quando 'Simular Cores' está ligado, eles são exibidos nas cores fonte.", + "instruction": "Arraste o ponto grande azul para mover o observador." + } + }, + "simulateColors": { + "title": "Simular Cores", + "description": "Simular cores (comprimentos de onda) de fontes luminosas, mistura de cores, filtragem de cores por bloqueadores e espelhos, e dispersão cromática de vidros.", + "instruction": "Você pode definir esses parâmetros para esses objetos quando selecionados. Para simular espectros de cor, sobreponha raios com comprimentos de onda diferentes.", + "warning": "As cores exibidas na tela são apenas aproximações, e podem ser muito imprecisas quando 'Densidade de Raios' está muito alta ou muito baixa." + }, + "languageDropdown": { + "title": "Linguagem: {{language}}", + "translatedFraction": "{{fraction}} traduzido" + } +} \ No newline at end of file diff --git a/locales/pt-BR/simulator.json b/locales/pt-BR/simulator.json new file mode 100644 index 00000000..98cf67d3 --- /dev/null +++ b/locales/pt-BR/simulator.json @@ -0,0 +1,335 @@ +{ + "welcome": { + "title": "Bem-vindo à Simulação de Óptica de Raios", + "instruction": "Para adicionar um componente ótico, selecione uma ferramenta e clique no espaço vazio.\nPara carregar um exemplo, por favor [visite a página da Galeria](/gallery).", + "loading": "Carregando cena a partir de URL... Por favor aguarde." + }, + "common": { + "saveButton": "Salvar", + "cancelButton": "Cancelar", + "defaultOption": "Padrão", + "closeButton": "Fechar" + }, + "file": { + "title": "Arquivo", + "undo": { + "title": "Desfazer" + }, + "redo": { + "title": "Refazer" + }, + "reset": { + "title": "Reiniciar" + }, + "save": { + "title": "Salvar" + }, + "open": { + "title": "Abrir", + "description": "Abrir um arquivo existente ou imagem de fundo. A imagem de fundo será exibida a partir origem das coordenadas. (Ou solte o arquivo)" + }, + "export": { + "title": "Exportar como PNG/SVG" + }, + "copyLink": { + "title": "Copiar Link Compartilhável", + "description": "Copiar e ir para a URL direta da cena atual, que pode ser utilizada para compartilhamento(possivelmente via encurtador de URL). Também veja Configurações -> Sincronização automática de URL." + }, + "viewGallery": { + "title": "Ver Galeria", + "description": "Ir para a página web da Galeria para carregar um exemplo." + } + }, + "settings": { + "title": "Configurações", + "more": "Mais", + "rayDensity": { + "title": "Densidade de Raios", + "description": "Determina o número de raios a serem emitidos por feixes e fontes pontuais. Isso também afeta a precisão da detecção de imagens e da reprodução de cores." + }, + "layoutAids": { + "title": "Auxílio de posicionamento", + "showGrid": "Grade", + "snapToGrid": "Ajustar na grade", + "lockObjs": "Travar Objetos" + }, + "gridSize": { + "title": "Tamanho da Grade" + }, + "observerSize": { + "title": "Tamanho do Observador" + }, + "lengthScale": { + "title": "Escala de Comprimento", + "description": "Se a unidade padrão de comprimento estiver pequena demais ou grande demais para modelar um sistema físico quando interpretado como uma unidade física comum unit (ex.: milímetros), esse fator pode ser usado para alterar a escala da aparência (ex.: larguras de linha) na cena." + }, + "zoom": { + "title": "Zoom" + }, + "language": { + "title": "Linguagem" + }, + "autoSyncUrl": { + "title": "Sincronizar URL automaticamente", + "description": "Quando habilitado, a URL será atualizada automaticamente com a cena atual, então você não precisa de ficar salvando a cena manualmente. Para definir o título, use Arquivo -> Salvar -> Renomear" + }, + "showJsonEditor": { + "title": "Exibir editor JSON", + "description": "Exibir o editor de código para a representação JSON da cena, que é necessária quando criando um módulo personalizado (Ver Ferramentas -> Outros -> Importar Módulos -> Criar módulos personalizados)." + }, + "showStatusBox": { + "title": "Exibir caixa de status", + "description": "Exibir a caixa de status, que inclui as coordenadas do mouse, informação de performance e o brilho truncado (o brilho total dos raios truncados na série infinita de reflexão interna)." + }, + "showHelpPopups": { + "title": "Exibir popups de ajuda", + "description": "Define se vai exibir popups de ajuda quando pairando sobre botões. (Recarregue a página para fazer efeito.)" + }, + "advancedHelp": "Para ajuda avançada, veja o ícone de ajuda no canto inferior direito." + }, + "objBar": { + "showAdvanced": { + "title": "Mais opções..." + }, + "applyToAll": { + "title": "Aplicar em Todos" + }, + "duplicate": { + "title": "Duplicar" + }, + "delete": { + "title": "Apagar" + }, + "unselect": { + "title": "Desselecionar", + "description": "Desselecionar esse objeto (Botão direito do mouse em espaço vazio tem a mesma função.)" + } + }, + "sceneObjs": { + "common": { + "lengthUnitInfo": "A unidade de comprimento utilizada nesse simulador (exceto comprimentos de onda) é arbitrária e pode ser interpretada como qualquer unidade física (ex.: milímetros) contanto que seja dentro da simulação. Se aunidade parecer pequena ou grande demais, por favor, ajuste Configurações -> Escala de Comprimento.", + "brightness": "Brilho", + "brightnessInfo": { + "rayDensity": "Somente faz efeito quando 'Densidade de Raios' está alta o suficiente.", + "rayDensitySlider": "Para controlar o número de raios emitidos, por favor ajuste o controle global de 'Densidade de Raios'." + }, + "wavelength": "Comprimento de onda", + "emisAngle": "Ângulo de Emissão", + "random": "Aleatório", + "lambert": "Lambertiano", + "focalLength": "Comprimento focal", + "eqnInfo": { + "constants": "Constantes suportadas", + "operators": "Operadores suportados", + "functions": "Funções suportadas" + }, + "imageDetectionWarning": "Esta ferramenta não suporta detecção de imagem.", + "nonSimulateColorsWarning": "Esta ferramenta só funciona quando \"Simular Cores\" está ligado." + }, + "Beam": { + "imageDetectionWarning": "Detecção de imagem pode não funcionar com raios aleatórios/divergentes." + }, + "AngleSource": { + "symmetric": "Simétrico" + }, + "BaseFilter": { + "filter": "Filtro", + "bandwidth": "Largura de banda", + "invert": "Inverter" + }, + "IdealMirror": { + "cartesianSign": "Convenção de Sinal Cartesiana" + }, + "BeamSplitter": { + "transRatio": "Razão de Transmissão" + }, + "BaseGlass": { + "refIndex": "Índice refrativo", + "refIndexInfo": { + "relative": "Relativo se dentro de outro vidro", + "effective": "Se este objeto deve ser simulado com índice refrativo absoluto n₁, mas estiver dentro de outro vidro de índice refrativo n₀, então você deve definir o índice refrativo como n₁/n₀ aqui. Em casos mais complicados que vários vidros se sobreponham, o índice refrativo efetivo da região sobreposta é igual ao produto dos índices refrativos individuais." + }, + "cauchyCoeff": "Coeficiente de Cauchy" + }, + "SphericalLens": { + "defBy": { + "radiiOfCurvature": "Raios de curvatura", + "focalDistances": "Distâncias Focais" + } + }, + "BaseGrinGlass": { + "refIndexFnInfo": { + "constants": "Constantes suportadas", + "operators": "Operadores suportados", + "functions": "Funções suportadas", + "lambda": "To simulate chromatic dispersion, use parameter {{lambda}} for the vacuum wavelength in nanometers.", + "diff": "Somente suporta funções diferenciáveis.", + "origin": "A origem de n(x,y) está em coordenadas absolutas e n~~ao move com o objeto. Você pode clicar duas vezes em um ponto de controle para inspecionar suas coordenadas absolutas.", + "accuracy": "Para simulação mais precisa, veja \"Mais opções...\"" + }, + "refIndexFnOrigin": "Origem de n(x,y)", + "stepSize": "Tamanho de passo da solução numérica", + "stepSizeInfo": "Tamanho de passo do método de Euler para resolver a equação do eikonal de raios - ver função 'step' e documentação dentro do arquivo 'BaseGrinGlass.js', para mais informações.", + "intersectTol": "Tolerância de Interseção", + "symbolicBodyMerging": "União simbólica de corpos", + "symbolicBodyMergingInfo": { + "all": "Esta opção se aplica a todos objetos GRIN na simulação.", + "impl": "Este simulador atualmente possi duas implementações de propagação de luz entre meios diferentes, para objetos GRIN - numérica e simbólica (ver funções 'multRefIndex' e 'devRefIndex' em 'BaseGrinGlass.js').", + "implNote": "A implementação numérica é mais rápida mas nem sempre funciona corretamente (dependende do caso específico) em cenários quando é usada com mais de um objeto GRIN, tal que ao menos um deles possua uma função de índice refrativo que não é definida todo o plano, enquanto a implementação simbólica é mais lenta, mas robusta a esse tipo de problema." + } + }, + "CircleGrinGlass": { + "epsInfo": { + "units": "Units - [length]^2.", + "functions": "Essa tolerância numérica é usada nas funções 'isOutsideGlass', 'isInsideGlass' e 'isOnBoundary', dentro do arquivo 'CircleGrinGlass.js'." + } + }, + "GrinGlass": { + "epsInfo": { + "units": "Units - [length].", + "functions": "Essa tolerância numérica é usada nas funções 'isOnBoundary' e 'countIntersections', dentro do arquivo'GrinGlass.js'." + } + }, + "Aperature": { + "diameter": "Diâmetro" + }, + "DiffractionGrating": { + "lineDensity": "Linhas/{{lengthUnit}}", + "customBrightness": "Brilho Personalizado", + "customBrightnessInfo": "Quando ligado, os brilhos dos raios difratados são personalizados por uma lista de números correspndendo a m = 0, 1, -1, 2, -2, .... O número será normalizado ao brilho do raio incidente. Os valores não na lista são definidos como 0. Por exemplo, \"1, 0.5, 0.5\" significa que o raio m=0 tem o mesmo brilho que o raio incidente, os raios m=1 e m=-1 têm metade do brilho, e todos os outros raios são ignorados.", + "slitRatio": "Largura de vão / Espaçamento de linha", + "mirrored": "Espelhado" + }, + "Ruler": { + "scaleInterval": "Intervalo da escala" + }, + "Detector": { + "info": { + "P": "P: A taxa de fluxo de energia em B/s (ver abaixo).", + "Fperp": "F⊥: A taxa de fluxo de momento perpendicular em (B/s)/c.", + "Fpar": "F∥: A taxa de fluxo de momento paralelo em (B/s)/c.", + "irradiance": "A irradiância no CSV exportado está em (B/s)/L.", + "length": "L é a unidade arbitrária de comprimento utilizada nesse simulador.", + "B": "B é uma unidade arbitrária de fluxo radiante ou fluxo luminoso, correspondente à unidade da opção \"Brilho\" sendo B/L para raios não Lambertianos e 500B/360° para fontes pontuais.", + "s": "O fator adimensional s é a \"Escala de Brilho\" exibida em Configurações -> Mostrar caixa de status, que é igual a 1 quando \"Densidade de Raios\" está acima de certo ponto e proporcional a \"Densidade de Raios\" caso contrário.", + "truncation": "Se alguns raios forem truncados na série infinita de reflexão interna, a truncação total é exibida como estimativas de erro." + }, + "irradMap": "Mapa de Irradiância", + "binSize": "Tamanho do coletor", + "exportData": "Exportar dados" + }, + "TextLabel": { + "textHere": "Texto Aqui", + "fontSize": "Tamanho da Fonte", + "font": "Fonte", + "fontStyle": "Estilo", + "fontStyles": { + "normal": "Normal", + "bold": "Negrito", + "italic": "Itálico", + "boldItalic": "Negrito Itálico", + "oblique": "Oblíquo", + "boldOblique": "Negrito Oblíquo" + }, + "alignment": "Alinhamento", + "alignments": { + "left": "Esquerda", + "center": "Centro", + "right": "Direita" + }, + "smallCaps": "Maiúsculo pequeno", + "angle": "Ângulo" + }, + "LineArrow": { + "arrow": "Seta frontal", + "backArrow": "Seta traseira" + }, + "Drawing": { + "finishDrawing": "Finalizar Desenho" + }, + "ModuleObj": { + "module": "Módulo", + "demodulize": "Demodulizar" + }, + "Handle": { + "handle": "Ponto de manuseio", + "transformation": "Transformação", + "transformations": { + "translation": "Translação", + "xTranslation": "Translação X", + "yTranslation": "Translação Y", + "rotation": "Rotação", + "scaling": "Escala" + } + }, + "CropBox": { + "title": "Exportar", + "cropBoxSize": "Tamanho da Caixa de Corte", + "format": "Formato", + "width": "Largura", + "rayCountLimit": "Limite de quantidade de raios", + "svgWarning": "Exportar como SVG: Misturas de cores e índices refrativos relativos abaixo de 1 não são suportados.", + "rayCountWarning": "O número atual de raios na cena é maior que o limite de número de raios. Você pode precisar de aumentar o limite nas opções da Caixa de Corte." + } + }, + "saveModal": { + "title": "Salvar", + "description": { + "autoSync": "Você pode usar Configurações -> Sincronizar URL automaticamente ao invés de salvar para um arquivo.", + "rename": "Clique \"Renomear\" para mudar o título sem salvar um arquivo.", + "contribute": "Você pode considerar [contribuir um novo item](/contributing/gallery) para a [Galeria](/gallery)." + }, + "fileName": "Nome", + "rename": "Renomear" + }, + "moduleModal": { + "title": "Importar Módulos", + "makeCustomModules": "Criar módulos personalizados", + "conflict": "Outro módulo com o mesmo nome já existe na cena atual. Você pode colocar outro nome, ou deixá-lo igual para sobrepor o módulo existente." + }, + "languageModal": { + "title": "Linguagem", + "translatedFraction": "traduzido", + "helpTranslate": "Ajude-nos a traduzir este aplicativo" + }, + "generalWarnings": { + "shareLinkTooLong": "Talvez a URL seja comprida demais para funcionar em algumas plataformas. Você pode precisar de usar \"Salvar\" e compartilhar o arquivo ao invés disso.", + "autoSyncUrlTooLarge": "A cena é grande demais para sincronizar com URL. Por favor, salve manualmente", + "identicalObjects": "Há dois elementos ópticos idênticos na cena que se sobrepõem completamente.", + "brightnessInconsistent": "O brilho de duas ou mais fontes de luz satura com razões inconsistentes. Isso pode levar a erros nas leituras do detector e reprodução de cores. Por favor aumente a densidade de raios ou reduza os brilhos das fontes luminosas." + }, + "statusBox": { + "rayCount": "Número de segmentos de raio", + "totalTruncation": "Brilho truncado", + "brightnessScale": "Escala de Brilho", + "timeElapsed": "Tempo decorrido", + "forceStopped": "Interrompido à força.", + "mouseCoordinates": "Coordenadas do Mouse" + }, + "footer": { + "processing": "Processando... Clique aqui para parar.", + "helpPopup": { + "constrainedDragging": { + "title": "Arraste restrito", + "description": "Enquanto arrasta um objeto, segure Shift para limitar ao sentido horizontal/vertical; segure Ctrl para clonar. Quando criando um objeto em formato de linha ou arrastando seus pontos finais, segure Shift para travar o ângulo ou ajustar para 0°, 45°, 90°; segure Ctrl para rotacionar/ajustar escala com relação a seu centro." + }, + "groupRotateScale": { + "title": "Agrupar, rotacionar e ajustar escala de objetos", + "description": "Segure Ctrl, clique em vários pontos de controle, então clique em espaço vazio para agrupar esses pontos e criar um ponto de manuseio. Arraste o ponto de manuseio (ou use as setas do teclado) para mover o grupo; Shift+arraste para limitar a horizontal/vertical; Ctrl+arraste para rotacionar, Ctrl+Shift+arraste para ajustar escala. Arraste o \"+\" para definir o centro de rotação/escala. Clique no ponto de manuseio e aperte Ctrl+D para duplicar o grupo; aperte Delete para desagrupar." + }, + "editCoordinates": { + "title": "Editar coordenadas diretamente", + "description": "Clique duplo ou clique com botão direito no ponto de controle do objeto, edite as coordenadas (x,y), então aperte Enter." + }, + "keyboardShortcuts": { + "title": "Atalhos de teclado", + "description": "Quando um objeto está selecionado (ao clicar nele), aperte as setas do teclado para movê-lo; Ctrl+D para duplicar; tecla Delete para apagar." + }, + "contactUs": { + "title": "Contate-nos", + "description": "O jeito sugerido é ir até [Discussões](/github/discussions) ou [Problemas](/github/issues) no GitHub. Se você não usar o GitHub, pode nos mandar um email em [ray-optics@phydemo.app](/email) (por favor use Inglês).", + "contribute": "Contribuições diretas também são bem-vindas (ver [o guia de contribuições](/contributing))." + } + } + } +} \ No newline at end of file diff --git a/locales/ru.json b/locales/ru.json deleted file mode 100644 index e33e4d32..00000000 --- a/locales/ru.json +++ /dev/null @@ -1,1048 +0,0 @@ -{ - "appName": { - "message": "Симуляция оптических лучей" - }, - "appShortName": { - "message": "Лучевая оптика" - }, - "appDesc": { - "incomplete": true, - "message": "A free, open-source web app for creating and simulating 2D geometric optical scenes." - }, - "homepage_desc": { - "incomplete": true, - "message": "Create & simulate 2D geometric optical scenes interactively.
Totally free and web-based. Source code is available on GitHub." - }, - "launch_simulator": { - "incomplete": true, - "message": "Launch Simulator" - }, - "home": { - "incomplete": true, - "message": "Home" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/ru/" - }, - "gallery": { - "incomplete": true, - "message": "Gallery" - }, - "gallery_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
To add an optical component, select a tool and click the blank space.
To load an example, please go to the Gallery page." - }, - "loading_msg": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
Loading scene from URL... Please wait." - }, - "toolbar_title": { - "message": "Инструмент: " - }, - "toolname_SingleRay": { - "message": "Луч" - }, - "toolname_AngleSource": { - "message": "Точечный источник" - }, - "toolname_PointSource": { - "message": "Точечный источник" - }, - "toolname_Beam": { - "message": "Пучок" - }, - "toolname_mirror_": { - "message": "Зеркало" - }, - "toolname_Mirror": { - "message": "Зеркало" - }, - "toolname_ArcMirror": { - "message": "Зеркало" - }, - "toolname_ParabolicMirror": { - "message": "Зеркало" - }, - "toolname_CustomMirror": { - "incomplete": true, - "message": "Mirror" - }, - "toolname_IdealMirror": { - "message": "Идеальное кривое зеркало" - }, - "toolname_glass_": { - "message": "Стекло" - }, - "toolname_blocker_": { - "message": "Поглощающая поверхность" - }, - "toolname_BeamSplitter": { - "incomplete": true, - "message": "Beam Splitter" - }, - "toolname_PlaneGlass": { - "message": "Стекло" - }, - "toolname_CircleGlass": { - "message": "Стекло" - }, - "toolname_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_Glass": { - "message": "Стекло" - }, - "toolname_GrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_IdealLens": { - "message": "Идеальная линза" - }, - "toolname_SphericalLens": { - "incomplete": true, - "message": "Spherical lens" - }, - "toolname_CustomGlass": { - "incomplete": true, - "message": "Glass" - }, - "toolname_Blocker": { - "incomplete": true, - "message": "Line Blocker" - }, - "toolname_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "toolname_CircleBlocker": { - "incomplete": true, - "message": "Circle Blocker" - }, - "toolname_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "toolname_Ruler": { - "message": "Линейка" - }, - "toolname_Protractor": { - "message": "Транспортир" - }, - "tool_Detector": { - "incomplete": true, - "message": "Detector" - }, - "toolname_Detector": { - "incomplete": true, - "message": "Detector" - }, - "toolname_TextLabel": { - "incomplete": true, - "message": "Text" - }, - "toolname_LineArrow": { - "incomplete": true, - "message": "Line" - }, - "toolname_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "toolname_Handle": { - "incomplete": true, - "message": "Handle" - }, - "toolname_CropBox": { - "incomplete": true, - "message": "Export" - }, - "toolname_ModuleObj": { - "incomplete": true, - "message": "ModuleBeta" - }, - "tool_more_": { - "message": "Другое" - }, - "toolname_": { - "message": "Движение камеры" - }, - "modebar_title": { - "message": "Вид:" - }, - "modename_light": { - "message": "Лучи" - }, - "modename_extended_light": { - "message": "Лучи с продолжениями" - }, - "modename_images": { - "message": "Все изображения" - }, - "modename_observer": { - "message": "Видимые наблюдателем" - }, - "simulateColors": { - "incomplete": true, - "message": "Simulate Colors" - }, - "File: ": { - "message": "Файл" - }, - "Tools: ": { - "message": "Инструменты" - }, - "tool_SingleRay": { - "message": "Луч" - }, - "tool_Beam": { - "message": "Пучок" - }, - "tool_PointSource": { - "message": "Точечный источник (360°)" - }, - "tool_AngleSource": { - "message": "Точечный источник (<360°)" - }, - "tool_PointSource_": { - "message": "Точечный источник" - }, - "tool_lightSource_": { - "message": "Источник света" - }, - "tool_mirror_": { - "message": "Зеркала" - }, - "tool_Mirror": { - "message": "Плоское" - }, - "tool_ArcMirror": { - "message": "Дуговое" - }, - "tool_ParabolicMirror": { - "incomplete": true, - "message": "Parabolic" - }, - "tool_CustomMirror": { - "incomplete": true, - "message": "Custom Equation" - }, - "tool_BeamSplitter": { - "incomplete": true, - "message": "Beam Splitter" - }, - "tool_IdealMirror": { - "message": "Идеальное кривое" - }, - "tool_glass_": { - "message": "Стекло" - }, - "tool_blocker_": { - "message": "Блокиратор" - }, - "tool_PlaneGlass": { - "message": "Полуплоскость" - }, - "tool_CircleGlass": { - "message": "Круг" - }, - "tool_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index circle" - }, - "tool_Glass": { - "incomplete": true, - "message": "Polygon / Circular Arcs" - }, - "tool_GrinGlass": { - "incomplete": true, - "message": "Gradient-index polygon" - }, - "tool_IdealLens": { - "message": "Идеальная линза" - }, - "tool_SphericalLens": { - "incomplete": true, - "message": "Spherical Lens" - }, - "tool_CustomGlass": { - "incomplete": true, - "message": "Custom Equation" - }, - "tool_Blocker": { - "incomplete": true, - "message": "Line Blocker" - }, - "tool_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "tool_CircleBlocker": { - "incomplete": true, - "message": "Circle Blocker" - }, - "tool_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "tool_Ruler": { - "message": "Линейка" - }, - "tool_Protractor": { - "message": "Транспортир" - }, - "tool_TextLabel": { - "incomplete": true, - "message": "Text" - }, - "tool_LineArrow": { - "incomplete": true, - "message": "Line / Arrow" - }, - "tool_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "tool_": { - "message": "Движение камеры" - }, - "View: ": { - "message": "Вид" - }, - "Settings: ": { - "message": "Настройки" - }, - "moresettings": { - "incomplete": true, - "message": "More" - }, - "mode_rays": { - "message": "Лучи" - }, - "mode_extended": { - "message": "Лучи с продолжениями" - }, - "mode_images": { - "message": "Все изображения" - }, - "mode_observer": { - "message": "Видимые наблюдателем" - }, - "zoom": { - "message": "Масштаб" - }, - "help": { - "message": "Помощь" - }, - "rayDensity": { - "message": "Плотность лучей" - }, - "raydensity": { - "message": "Плотность лучей:" - }, - "undo": { - "message": "Отмена" - }, - "redo": { - "message": "Повтор" - }, - "reset": { - "message": "Сброс" - }, - "save": { - "message": "Сохранить" - }, - "rename": { - "incomplete": true, - "message": "Rename" - }, - "get_link": { - "incomplete": true, - "message": "Copy Shareable Link" - }, - "export_svg": { - "incomplete": true, - "message": "Export as PNG/SVG" - }, - "view_gallery": { - "incomplete": true, - "message": "View Gallery" - }, - "save_name": { - "message": "Название" - }, - "save_cancel": { - "message": "Отмена" - }, - "save_description": { - "incomplete": true, - "message": "
  • You may use Settings -> Auto sync URL instead of saving to a file.
  • Click \"Rename\" to change the title without saving to a file.
  • You may consider contribute a new item to the Gallery.
" - }, - "open": { - "message": "Открыть" - }, - "layoutaids": { - "incomplete": true, - "message": "Layout Aids" - }, - "lockObjs": { - "incomplete": true, - "message": "Lock Objects" - }, - "showGrid": { - "message": "Сетка" - }, - "snapToGrid": { - "message": "Клеиться к сетке" - }, - "snaptogrid": { - "message": "Клеиться к сетке" - }, - "length_unit_popover": { - "incomplete": true, - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "incomplete": true, - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "incomplete": true, - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "message": "Яркость" - }, - "wavelength": { - "message": "Длина волны (nm)" - }, - "dichroic": { - "message": "Дихроик" - }, - "filter": { - "message": "Фильтр" - }, - "bandwidth": { - "message": "Пропускная способность (nm)" - }, - "invert": { - "message": "Инвертировать" - }, - "emisAngle": { - "incomplete": true, - "message": "Emission Angle (°)" - }, - "mirrored": { - "incomplete": true, - "message": "Mirrored" - }, - "lineDensity": { - "incomplete": true, - "message": "Lines/mm" - }, - "slitRatio": { - "incomplete": true, - "message": "Slit width / line spacing" - }, - "customBrightness": { - "incomplete": true, - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "incomplete": true, - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "incomplete": true, - "message": "Symmetric" - }, - "eqn_note": { - "incomplete": true, - "message": "
  • Supported constants:
    pi e
  • Supported operators:
    + - * / ^
  • Supported functions:
    sqrt sin cos tan sec csc cot sinh cosh tanh log exp arcsin arccos arctan arcsinh arccosh arctanh floor round ceil trunc sgn max min abs
" - }, - "symbolic_grin": { - "incomplete": true, - "message": "Symbolic body-merging" - }, - "grin_refractive_index": { - "incomplete": true, - "message": "
  • Supported constants:
    pi e
  • Supported operators:
    + - * / ^
  • Supported functions:
    sqrt sin cos tan sec csc cot sinh cosh tanh log arcsin arccos arctan
  • To simulate chromatic dispersion, use parameter lambda for the vacuum wavelength in nanometers.Beta
  • Only supports differentiable functions.
  • The origin of n(x,y) is in the absolute coordinates and does not move with the object. You may double-click a control-point to inspect its absolute coordinates.
  • For a more accurate simulation, see \"More options...\"
" - }, - "symbolic_grin_note_popover": { - "incomplete": true, - "message": "

This toggle applies to all GRIN objects in the simulation.

This simulator has currently two implementations of light propagation between different mediums, for GRIN objects - numerical and symbolic (see 'multRefIndex' and 'devRefIndex' functions in 'CircleGrinGlass.js').

The numerical implementation is faster but doesn't always work properly (depending on the specific case) in scenarios when used with more than one GRIN object, such that at least one of them has a refractive index function which is not defined in the entire plane, while the symbolic implementation is slower but robust to such problems.

" - }, - "focalLength": { - "message": "Фокальное расстояние" - }, - "cartesianSign": { - "incomplete": true, - "message": "Cartesian Sign Convention" - }, - "refIndex": { - "message": "Показатель преломления*" - }, - "radii_of_curvature": { - "incomplete": true, - "message": "Radii of Curvature" - }, - "focal_distances": { - "incomplete": true, - "message": "Focal Distances" - }, - "refIndex_origin": { - "incomplete": true, - "message": "Origin of n(x,y)" - }, - "stepSize": { - "incomplete": true, - "message": "Numerical solver step size" - }, - "intersectTol": { - "incomplete": true, - "message": "Intersection tolerance" - }, - "random": { - "incomplete": true, - "message": "Random" - }, - "lambert": { - "incomplete": true, - "message": "Lambertian" - }, - "diameter": { - "incomplete": true, - "message": "Diameter" - }, - "irradMap": { - "incomplete": true, - "message": "Irradiance Map" - }, - "binSize": { - "incomplete": true, - "message": "Bin Size" - }, - "scaleInterval": { - "incomplete": true, - "message": "Scale interval" - }, - "exportData": { - "incomplete": true, - "message": "Export data" - }, - "demodulize": { - "incomplete": true, - "message": "Demodulize" - }, - "fontSize": { - "incomplete": true, - "message": "Font Size" - }, - "font": { - "incomplete": true, - "message": "Font" - }, - "fontStyle": { - "incomplete": true, - "message": "Style" - }, - "normal": { - "incomplete": true, - "message": "Normal" - }, - "bold": { - "incomplete": true, - "message": "Bold" - }, - "italic": { - "incomplete": true, - "message": "Italic" - }, - "bolditalic": { - "incomplete": true, - "message": "Bold Italic" - }, - "oblique": { - "incomplete": true, - "message": "Oblique" - }, - "boldoblique": { - "incomplete": true, - "message": "Bold Oblique" - }, - "alignment": { - "incomplete": true, - "message": "Alignment" - }, - "left": { - "incomplete": true, - "message": "Left" - }, - "center": { - "incomplete": true, - "message": "Centre" - }, - "right": { - "incomplete": true, - "message": "Right" - }, - "text_here": { - "incomplete": true, - "message": "Text Here" - }, - "smallCaps": { - "incomplete": true, - "message": "Small Caps" - }, - "angle": { - "incomplete": true, - "message": "Angle (°)" - }, - "arrow": { - "incomplete": true, - "message": "Forward arrow" - }, - "backArrow": { - "incomplete": true, - "message": "Backward arrow" - }, - "stop_drawing": { - "incomplete": true, - "message": "Finish Drawing" - }, - "cropBoxSize": { - "incomplete": true, - "message": "Crop Box Size" - }, - "format": { - "incomplete": true, - "message": "Format" - }, - "width": { - "incomplete": true, - "message": "Width" - }, - "rayCountLimit": { - "incomplete": true, - "message": "Ray count limit" - }, - "transformation": { - "incomplete": true, - "message": "TransformationBeta" - }, - "default": { - "incomplete": true, - "message": "Default" - }, - "translation": { - "incomplete": true, - "message": "Translation" - }, - "xTranslation": { - "incomplete": true, - "message": "X Translation" - }, - "yTranslation": { - "incomplete": true, - "message": "Y Translation" - }, - "rotation": { - "incomplete": true, - "message": "Rotation" - }, - "scaling": { - "incomplete": true, - "message": "Scaling" - }, - "beam_warning": { - "incomplete": true, - "message": "Image detection may not work with divergent/random beams." - }, - "image_detection_warning": { - "incomplete": true, - "message": "This tool does not support image detection." - }, - "non_simulateColors_warning": { - "incomplete": true, - "message": "This tool only works when \"Simulate Color\" is on." - }, - "brightness_note_popover": { - "incomplete": true, - "message": "

Only effective if 'Ray Density' is high enough.

To control the numbers of rays emitted, please adjust the global 'Ray Density' slider instead.

" - }, - "refIndex_note_popover": { - "incomplete": true, - "message": "

*Relative if inside another glass

If this object is to be simulated with (absolute) refractive index n₁, but is placed inside another glass with refractive index n₀, then you should set the refractive index to n₁/n₀ here. In more complicated cases that several glasses overlap together, the effective reflective index of the overlapping region equals the product of the reflective indices of individual ones.

" - }, - "stepSize_note_popover": { - "incomplete": true, - "message": "

Step size of Euler's method for solving the eikonal ray equation - see 'step' function and documentation inside the 'CircleGrinGlass.js' file, for more information.

" - }, - "eps_CircleGrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length]^2.

This numerical tolerance is used in the functions 'isOutsideGlass', 'isInsideGlass' and 'isOnBoundary', inside the 'CircleGrinGlass.js' file.

" - }, - "eps_GrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length].

This numerical tolerance is used in the functions 'isOnBoundary' and 'countIntersections', inside the 'GrinGlass.js' file.

" - }, - "cauchyCoeff": { - "incomplete": true, - "message": "Cauchy coefficient" - }, - "transRatio": { - "incomplete": true, - "message": "Transmission Ratio" - }, - "applytoall": { - "message": "Применить ко всем" - }, - "duplicate": { - "message": "Дублировать" - }, - "delete": { - "message": "Удалить" - }, - "unselect": { - "incomplete": true, - "message": "Unselect" - }, - "unselect_popover": { - "incomplete": true, - "message": "Unselect this object (Right-click on blank space has the same function.)" - }, - "showadvanced": { - "incomplete": true, - "message": "More options..." - }, - "processing": { - "message": "Вычисление... Нажмите, чтобы остановить." - }, - "contribute": { - "incomplete": true, - "message": "Contribute" - }, - "github": { - "incomplete": true, - "message": "GitHub" - }, - "about": { - "incomplete": true, - "message": "About" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "incomplete": true, - "message": "Help us translate this app" - }, - "translated": { - "incomplete": true, - "message": "translated" - }, - "undo_popover": { - "message": "Отменить последнее действие. (Ctrl+Z)" - }, - "redo_popover": { - "message": "Повторить последнее действие. (Ctrl+Y)" - }, - "reset_popover": { - "message": "Сбросить все изменения." - }, - "save_popover": { - "incomplete": true, - "message": "Save the current scene as a file." - }, - "open_popover": { - "incomplete": true, - "message": "Open an existing file or background image. The background image will be shown from the coordinate origin. (Or drop the file)" - }, - "get_link_popover": { - "incomplete": true, - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "incomplete": true, - "message": "The URL is too long that it may not work on some platforms. You may need to use \"Save\" and share the file instead." - }, - "export_svg_warning": { - "incomplete": true, - "message": "Export to SVG: Color mixtures and relative refractive indices below 1 are not supported." - }, - "export_ray_count_warning": { - "incomplete": true, - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "incomplete": true, - "message": "Go to the Gallery webpage to load an example." - }, - "tool_SingleRay_popover": { - "message": "Одиночный луч света, задаваемый двумя точками. (Потяните или нажмите, чтобы создать. Первая точка - источник, испускающий луч в сторону второй точки.)" - }, - "tool_Beam_popover": { - "incomplete": true, - "message": "A parallel or divergent beam of rays emerges from a line segment, with density controlled by the 'Ray density' slider. (Drag or click to create.)" - }, - "tool_PointSource_popover": { - "message": "Лучи исходят из одной точки во всех направлениях. Количество лучей задается ползунком 'Плотность лучей'. (Нажмите, чтобы создать.)" - }, - "tool_AngleSource_popover": { - "incomplete": true, - "message": "Point source with a given emission angle." - }, - "tool_Mirror_popover": { - "message": "Симулирует отражение в зеркале. (Потяните или нажмите, чтобы создать.)" - }, - "tool_ArcMirror_popover": { - "message": "Зеркало в форме дуги. Задается тремя точками. (Потяните или нажмите, чтобы создать. Первые две точки задают концы дуги, последняя точка задает радиус окружности.)" - }, - "tool_ParabolicMirror_popover": { - "incomplete": true, - "message": "A mirror whose shape is a parabola, which is defined by three points. (Drag or click to create.)" - }, - "tool_CustomMirror_popover": { - "incomplete": true, - "message": "A mirror whose shape is defined by a custom equation y = f(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0). (Drag or click to create.)" - }, - "tool_BeamSplitter_popover": { - "incomplete": true, - "message": "A mirror that transmits a percentage of incoming light. (Drag or click to create.)" - }, - "tool_IdealMirror_popover": { - "message": "Идеальное 'кривое' зеркало, строго подчиняющееся уравнению зеркала (1/d + 1/f = 1/F). Фокальное расстояние задается. (Потяните или нажмите, чтобы создать.)" - }, - "tool_PlaneGlass_popover": { - "message": "Симулирует отражение и преломление света на поверхности. (Потяните или нажмите, чтобы создать.)" - }, - "tool_CircleGlass_popover": { - "message": "Стекло в форме круга. Задается центром и точкой. (Потяните или нажмите, чтобы создать.)" - }, - "tool_CircleGrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a circular boundary. (Drag or click to create.)" - }, - "tool_Glass_popover": { - "message": "Стекло с формой, состоящей из отрезков и дуг. (Нажмите, чтобы создать отрезок, потяните, чтобы создать дугу, нажмите на начальную точку, чтобы закончить фигуру.)" - }, - "tool_GrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a polygonal boundary. WARNING: Only simple polygons are supported, otherwise the behavior is unpredictable. (Click to create a segment, click on the starting point when finish drawing.)" - }, - "tool_IdealLens_popover": { - "message": "Идеальная линза, строго подчиняющаяся уравнению плоской линзы (1/d + 1/f = 1/F). Фокальное расстояние задается. (Потяните или нажмите, чтобы создать.)" - }, - "tool_SphericalLens_popover": { - "incomplete": true, - "message": "A spherical lens. (Click to create.)" - }, - "tool_CustomGlass_popover": { - "incomplete": true, - "message": "Glass with the shape defined by a custom inequality f(x) < y < g(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0). (Drag or click to create.)" - }, - "tool_Blocker_popover": { - "message": "Отрезок, поглощающий попадающие на него лучи. (Потяните или нажмите, чтобы создать.)" - }, - "tool_Aperture_popover": { - "incomplete": true, - "message": "A pair of light blockers which absorbs the incident rays. The size of the hole can be adjusted symmetrically. (Drag or click the two endpoints to create.)" - }, - "tool_CircleBlocker_popover": { - "incomplete": true, - "message": "A circle light blocker which absorbs the incident rays. (Drag or click to create.)" - }, - "tool_DiffractionGrating_popover": { - "incomplete": true, - "message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)" - }, - "tool_Ruler_popover": { - "message": "Линейка от нуля до точки. (Потяните или нажмите, чтобы создать.)" - }, - "tool_Protractor_popover": { - "message": "Транспортир Ноль задается центром и другой точкой. Масштаб в градусах. (Потяните или нажмите, чтобы создать.)" - }, - "tool_Detector_popover": { - "incomplete": true, - "message": "A tool for measuring the rate of energy flow (P), the rate of perpendicular momentum flow (F⊥), and the rate of parallel momentum flow (F∥) through a line segment. (Drag or click to create the line segment.) The units are arbitrary." - }, - "tool_Detector_info_popover": { - "incomplete": true, - "message": "
  • P: The rate of energy flow (flux) in B/s (see below).
  • F⊥: The rate of perpendicular momentum flow in (B/s)/c.
  • F∥: The rate of parallel momentum flow in (B/s)/c.
  • The irradiance in the exported CSV is in (B/s)/L.
  • L is the arbitrary unit of length used in this simulator.
  • B is an arbitrary unit of radiant flux or luminous flux, corresponding to the unit of the \"Brightness\" option being B/L for non-Lambertian beams and 500B/360° for point sources.
  • The dimensionless factor s is the \"Brightness Scale\" shown in Settings -> Show status box, which equals 1 when \"Ray Density\" is above some threshold and proportional to \"Ray Density\" otherwise.
  • If some rays are truncated in the infinite series of internal reflection, the total truncation is shown as error estimates.
" - }, - "tool_TextLabel_popover": { - "incomplete": true, - "message": "A text label." - }, - "tool_LineArrow_popover": { - "incomplete": true, - "message": "A line segment or arrow. (Drag or click to create.)" - }, - "tool_Drawing_popover": { - "incomplete": true, - "message": "A freehand drawing tool. (Drag to draw.)" - }, - "tool__popover": { - "message": "Потяните, чтобы переместить камеру. (Также можно потянуть правой кнопкой мыши.)" - }, - "mode_rays_popover": { - "message": "Показывает лучи. Если 'Плотность лучей' высока, они выглядят цельным пучком." - }, - "mode_extended_popover": { - "incomplete": true, - "message": "Show both the rays and its extension. Orange indicates backward extensions, and gray indicates forward ones.
When 'Simulate Colors' is on, they are shown in source colors and distinguished by dashing instead." - }, - "mode_images_popover": { - "incomplete": true, - "message": "Show the position of all images. Yellow points indicate real images, orange indicates virtual images, and gray (none in this picture) indicates virtual objects. Note that some images cannot be detected if 'Ray density' is not high enough.
When 'Simulate Colors' is on, they are shown in source colors and distinguished by dot sizes instead." - }, - "mode_observer_popover": { - "incomplete": true, - "message": "Simulate the rays and images seen from some position. The blue circle is the observer. Any rays crossing it are considered to be 'observed'. The observer does not know where the rays actually begin, but may think they begin at some point(s) if they intersect there. The rays are shown in blue, and the points in yellow (real) or orange (virtual). (Drag the big blue dot to move the observer.)
When 'Simulate Colors' is on, they are shown in source colors instead." - }, - "simulateColors_popover": { - "incomplete": true, - "message": "Simulate colors (wavelengths) of light sources, mixture of colors, color filtering of blockers and mirrors, and chromatic dispersion of glasses. You can set those parameters for those objects when selected. To simulate color spectra, overlap rays with different wavelengths. The colors shown on the screen are only rough approximations, and can be very inaccurate when 'Ray density' is too high or too low." - }, - "rayDensity_popover": { - "incomplete": true, - "message": "Determines the number of rays to be emitted by beams and point sources. This also affects the accuracy of image detection and color rendering." - }, - "showGrid_popover": { - "message": "Включить или выключить сетку." - }, - "grid_popover": { - "message": "Включить или выключить приклейку к сетке." - }, - "lockObjs_popover": { - "message": "Разрешить или нет перемещение объектов." - }, - "zoom_popover": { - "message": "Увеличить или уменьшить масштаб." - }, - "help_popover": { - "incomplete": true, - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "incomplete": true, - "message": "Show help popups" - }, - "show_help_popups_popover": { - "incomplete": true, - "message": "Defines whether to show help popups when hovering over buttons. (Reload the page to take effect.)" - }, - "show_json_editor": { - "incomplete": true, - "message": "Show JSON editorBeta" - }, - "show_json_editor_popover": { - "incomplete": true, - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "incomplete": true, - "message": "Show status box" - }, - "show_status_popover": { - "incomplete": true, - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "incomplete": true, - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "incomplete": true, - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "incomplete": true, - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "incomplete": true, - "message": "Grid Size" - }, - "observer_size": { - "incomplete": true, - "message": "Observer Size" - }, - "language": { - "incomplete": true, - "message": "Language" - }, - "close": { - "incomplete": true, - "message": "Close" - }, - "advanced_help": { - "incomplete": true, - "message": "For advanced help, see the help icon in the lower-right corner." - }, - "ray_count": { - "incomplete": true, - "message": "Number of ray segments: " - }, - "total_truncation": { - "incomplete": true, - "message": "Truncated brightness: " - }, - "brightness_scale": { - "incomplete": true, - "message": "Brightness Scale: " - }, - "time_elapsed": { - "incomplete": true, - "message": "Time elapsed (ms): " - }, - "force_stopped": { - "incomplete": true, - "message": "Force stopped." - }, - "mouse_coordinates": { - "incomplete": true, - "message": "Mouse coordinates: " - }, - "modules_tutorial": { - "incomplete": true, - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "incomplete": true, - "message": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior." - }, - "import_modules": { - "incomplete": true, - "message": "Import Modules..." - }, - "import_modules_title": { - "incomplete": true, - "message": "Import Modules" - }, - "modules_url": { - "incomplete": true, - "message": "../modules/modules.html" - }, - "remove_module": { - "incomplete": true, - "message": "Remove module" - }, - "module_conflict": { - "incomplete": true, - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "incomplete": true, - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/ru/main.json b/locales/ru/main.json new file mode 100644 index 00000000..38c307de --- /dev/null +++ b/locales/ru/main.json @@ -0,0 +1,119 @@ +{ + "meta": { + "languageName": "Русский", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "Симуляция оптических лучей", + "shortName": "Лучевая оптика" + }, + "homePage": { + "description": "Веб-приложение с открытым исходным кодом симулируещее отражение и рефракцию света.\nНаписано на HTML, CSS и JavaScript. ([GitHub](/github))", + "launchSimulator": "Запустить приложение" + }, + "tools": { + "title": "Инструменты", + "categories": { + "lightSource": "Источник света", + "mirror": "Зеркала", + "glass": "Стекло", + "blocker": "Блокиратор", + "other": "Другое" + }, + "common": { + "clickInstruction": "Нажмите, чтобы создать.", + "lineInstruction": "Потяните или нажмите, чтобы создать.", + "circleInstruction": "Потяните или нажмите, чтобы создать." + }, + "SingleRay": { + "title": "Луч", + "description": "Одиночный луч света, задаваемый двумя точками.", + "instruction": "Потяните или нажмите, чтобы создать. Первая точка - источник, испускающий луч в сторону второй точки." + }, + "Beam": { + "title": "Пучок", + "description": "Пучок параллельных лучей, исходящих из отрезка, с плотностью лучей задаваемой ползунком 'Плотность лучей'. (Also supports divergent beams.)" + }, + "PointSource": { + "title": "Точечный источник", + "description": "Лучи исходят из одной точки во всех направлениях. Количество лучей задается ползунком 'Плотность лучей'." + }, + "AngleSource": { + "instruction": "Потяните или нажмите, чтобы создать. Первая точка - источник, испускающий луч в сторону второй точки." + }, + "Mirror": { + "title": "Плоское", + "description": "Симулирует отражение в зеркале." + }, + "otherMirror": { + "title": "Дуговое", + "description": "Зеркало в форме дуги. Задается тремя точками." + }, + "ArcMirror": { + "title": "Дуговое", + "description": "Зеркало в форме дуги. Задается тремя точками.", + "instruction": "Потяните или нажмите, чтобы создать. Первые две точки задают концы дуги, последняя точка задает радиус окружности." + }, + "IdealMirror": { + "title": "Идеальное кривое", + "description": "Идеальное 'кривое' зеркало, строго подчиняющееся уравнению зеркала (1/d + 1/f = 1/F). Фокальное расстояние задается." + }, + "PlaneGlass": { + "title": "Полуплоскость", + "description": "Симулирует отражение и преломление света на поверхности.", + "instruction": "Потяните или нажмите, чтобы создать." + }, + "otherGlass": { + "title": "Другое", + "description": "Стекло с формой, состоящей из отрезков и дуг." + }, + "CircleGlass": { + "title": "Круг", + "description": "Стекло в форме круга. Задается центром и точкой." + }, + "Glass": { + "description": "Стекло с формой, состоящей из отрезков и дуг.", + "instruction": "Нажмите, чтобы создать отрезок, потяните, чтобы создать дугу, нажмите на начальную точку, чтобы закончить фигуру." + }, + "IdealLens": { + "title": "Идеальная линза", + "description": "Идеальная линза, строго подчиняющаяся уравнению плоской линзы (1/d + 1/f = 1/F). Фокальное расстояние задается." + }, + "Blocker": { + "description": "Отрезок, поглощающий попадающие на него лучи." + }, + "Ruler": { + "title": "Линейка", + "description": "Линейка от нуля до точки." + }, + "Protractor": { + "title": "Транспортир", + "description": "Транспортир Ноль задается центром и другой точкой. Масштаб в градусах." + }, + "moveView": { + "title": "Движение камеры", + "description": "Потяните, чтобы переместить камеру. (Также можно потянуть правой кнопкой мыши.)" + } + }, + "view": { + "title": "Вид", + "rays": { + "title": "Лучи", + "description": "Показывает лучи. Если 'Плотность лучей' высока, они выглядят цельным пучком." + }, + "extended": { + "title": "Лучи с продолжениями" + }, + "images": { + "title": "Все изображения" + }, + "observer": { + "title": "Видимые наблюдателем" + } + }, + "languageDropdown": { + "title": "Язык: {{language}}" + } +} \ No newline at end of file diff --git a/locales/ru/simulator.json b/locales/ru/simulator.json new file mode 100644 index 00000000..561e4976 --- /dev/null +++ b/locales/ru/simulator.json @@ -0,0 +1,76 @@ +{ + "common": { + "saveButton": "Сохранить", + "cancelButton": "Отмена" + }, + "file": { + "title": "Файл", + "undo": { + "title": "Отмена" + }, + "redo": { + "title": "Повтор" + }, + "reset": { + "title": "Сброс" + }, + "save": { + "title": "Сохранить" + }, + "open": { + "title": "Открыть" + } + }, + "settings": { + "title": "Настройки", + "rayDensity": { + "title": "Плотность лучей" + }, + "layoutAids": { + "showGrid": "Сетка", + "snapToGrid": "Клеиться к сетке" + }, + "zoom": { + "title": "Масштаб" + }, + "language": { + "title": "Язык" + } + }, + "objBar": { + "applyToAll": { + "title": "Применить ко всем" + }, + "duplicate": { + "title": "Дублировать" + }, + "delete": { + "title": "Удалить" + } + }, + "sceneObjs": { + "common": { + "brightness": "Яркость", + "wavelength": "Длина волны", + "focalLength": "Фокальное расстояние" + }, + "BaseFilter": { + "filter": "Фильтр", + "bandwidth": "Пропускная способность", + "invert": "Инвертировать" + }, + "BaseGlass": { + "refIndex": "Показатель преломления" + } + }, + "saveModal": { + "title": "Сохранить", + "fileName": "Название" + }, + "languageModal": { + "title": "Язык" + }, + "footer": { + "processing": "Вычисление... Нажмите, чтобы остановить." + } +} \ No newline at end of file diff --git a/locales/si.json b/locales/si.json deleted file mode 100644 index 7cdd6503..00000000 --- a/locales/si.json +++ /dev/null @@ -1,925 +0,0 @@ -{ - "appName": { - "incomplete": true, - "message": "Simulator - Ray Optics Simulation" - }, - "appShortName": { - "incomplete": true, - "message": "Ray Optics" - }, - "appDesc": { - "message": "ද්විමාන ප්‍රකාශ(ආලෝක) දර්ශන නිර්මාණය කිරීම simulate කිරීම සඳහා free, open-source වෙබ් යෙදුමකි." - }, - "homepage_desc": { - "incomplete": true, - "message": "Create & simulate 2D geometric optical scenes interactively.
Totally free and web-based. Source code is available on GitHub." - }, - "launch_simulator": { - "message": "Simulator Launch කරන්න." - }, - "home": { - "message": "මුල් පිටුව" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/si/" - }, - "gallery": { - "message": "Gallery" - }, - "gallery_url": { - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "message": "Ray Optics Simulation වෙත සාදරයෙන් පිළිගනිමු
optical component එක් කිරීමට tool තෝරා හිස් අවකාශය මත click කරන්න.
උදාහරණ සඳහා Gallery page වෙත යන්න." - }, - "loading_msg": { - "message": "Ray Optics Simulation වෙත සාදරයෙන් පිළිගනිමු
URL වෙතින් දර්ශනය load වේ... කරුණාකර රැඳී සිටින්න." - }, - "toolbar_title": { - "message": "Tool: " - }, - "toolname_SingleRay": { - "message": "තනි කිරණ" - }, - "toolname_AngleSource": { - "message": "ආලෝක ප්‍රභවය" - }, - "toolname_PointSource": { - "message": "ආලෝක ප්‍රභවය" - }, - "toolname_Beam": { - "message": "ආලෝක කදම්භය" - }, - "toolname_mirror_": { - "message": "දර්පණය" - }, - "toolname_Mirror": { - "message": "දර්පණය" - }, - "toolname_ArcMirror": { - "message": "දර්පණය" - }, - "toolname_ParabolicMirror": { - "message": "දර්පණය" - }, - "toolname_CustomMirror": { - "message": "දර්පණය" - }, - "toolname_IdealMirror": { - "message": "වක්‍ර දර්පණය" - }, - "toolname_glass_": { - "message": "වීදුරු" - }, - "toolname_blocker_": { - "message": "බාධක" - }, - "toolname_BeamSplitter": { - "message": "කදම්භ විබෙදුම" - }, - "toolname_PlaneGlass": { - "message": "වීදුරු" - }, - "toolname_CircleGlass": { - "message": "වීදුරු" - }, - "toolname_CircleGrinGlass": { - "message": "අනුක්‍රමිකව වර්තනාංකය වෙනස් වන වීදුරු" - }, - "toolname_Glass": { - "message": "වීදුරු" - }, - "toolname_GrinGlass": { - "message": "අනුක්‍රමිකව වර්තනාංකය වෙනස් වන වීදුරු" - }, - "toolname_IdealLens": { - "message": "සාමාන්‍ය කාච" - }, - "toolname_SphericalLens": { - "message": "වක්‍ර කාච" - }, - "toolname_CustomGlass": { - "message": "වීදුරු" - }, - "toolname_Blocker": { - "message": "රේඛීය බාධක" - }, - "toolname_Aperture": { - "message": "විවරය" - }, - "toolname_CircleBlocker": { - "message": "වක්‍ර බාධක" - }, - "toolname_DiffractionGrating": { - "message": "විවර්තන තලයBeta" - }, - "toolname_Ruler": { - "message": "රූල" - }, - "toolname_Protractor": { - "message": "කෝණමානය" - }, - "tool_Detector": { - "message": "අනාවරකය" - }, - "toolname_Detector": { - "message": "අනාවරකය" - }, - "toolname_TextLabel": { - "incomplete": true, - "message": "Text" - }, - "toolname_LineArrow": { - "message": "රේඛාව" - }, - "toolname_Drawing": { - "message": "Drawing" - }, - "toolname_Handle": { - "incomplete": true, - "message": "Handle" - }, - "toolname_CropBox": { - "message": "Export" - }, - "toolname_ModuleObj": { - "message": "මොඩියුලBeta" - }, - "tool_more_": { - "message": "අමතර" - }, - "toolname_": { - "message": "Move view" - }, - "modebar_title": { - "message": "View" - }, - "modename_light": { - "message": "කිරණ" - }, - "modename_extended_light": { - "message": "දිගුකල කිරණ" - }, - "modename_images": { - "message": "ප්‍රතිබිම්භ සියල්ල" - }, - "modename_observer": { - "message": "නිරීක්ෂකයාට පෙනෙන පරිදි" - }, - "simulateColors": { - "message": "වර්ණ අනුකරණය" - }, - "File: ": { - "incomplete": true, - "message": "File" - }, - "Tools: ": { - "incomplete": true, - "message": "Tools" - }, - "tool_SingleRay": { - "message": "තනි ආලෝක කිරණයක්" - }, - "tool_Beam": { - "message": "ආලෝක කදම්භය" - }, - "tool_PointSource": { - "message": "ආලෝක ප්‍රභවය (360°)" - }, - "tool_AngleSource": { - "message": "ආලෝක ප්‍රභවය (<360°)" - }, - "tool_PointSource_": { - "message": "ආලෝක ප්‍රභවය" - }, - "tool_lightSource_": { - "message": "ආලෝක ප්‍රභවයන්" - }, - "tool_mirror_": { - "message": "දර්පණ" - }, - "tool_Mirror": { - "message": "කොටසක්" - }, - "tool_ArcMirror": { - "message": "වෘත්තාකාර චාප" - }, - "tool_ParabolicMirror": { - "message": "පරාවලයික" - }, - "tool_CustomMirror": { - "message": "Custom සමීකරණ" - }, - "tool_BeamSplitter": { - "message": "කදම්භ විබෙදුම" - }, - "tool_IdealMirror": { - "message": "පරිපූර්ණ වක්‍ර" - }, - "tool_glass_": { - "message": "වීදුරු" - }, - "tool_blocker_": { - "message": "බාධක" - }, - "tool_PlaneGlass": { - "message": "අර්ධ තලයක්" - }, - "tool_CircleGlass": { - "message": "වෘත්ත" - }, - "tool_CircleGrinGlass": { - "message": "අනුක්‍රමිකව වර්තනාංකය වෙනස් වන වෘත්තාකාර වීදුරුව" - }, - "tool_Glass": { - "incomplete": true, - "message": "Polygon / Circular Arcs" - }, - "tool_GrinGlass": { - "message": "අනුක්‍රමිකව වර්තනාංකය වෙනස් වන බහුඅස්‍ර" - }, - "tool_IdealLens": { - "message": "පරිපූර්ණ කාච" - }, - "tool_SphericalLens": { - "message": "වක්‍ර කාච" - }, - "tool_CustomGlass": { - "message": "Custom සමීකරණ" - }, - "tool_Blocker": { - "message": "‌රේඛීය බාධක" - }, - "tool_Aperture": { - "message": "විවරය" - }, - "tool_CircleBlocker": { - "message": "වක්‍ර බාධක" - }, - "tool_DiffractionGrating": { - "message": "විවර්තන තලයBeta" - }, - "tool_Ruler": { - "message": "රූල" - }, - "tool_Protractor": { - "message": "කෝණමානය" - }, - "tool_TextLabel": { - "message": "Text" - }, - "tool_LineArrow": { - "message": "රේඛා / ඊතල" - }, - "tool_Drawing": { - "message": "Drawing" - }, - "tool_": { - "message": "Move view" - }, - "View: ": { - "message": "View" - }, - "Settings: ": { - "message": "සැකසුම්" - }, - "moresettings": { - "message": "තවත්" - }, - "mode_rays": { - "message": "කිරණ" - }, - "mode_extended": { - "message": "දිගුකල කිරණ" - }, - "mode_images": { - "message": "ප්‍රතිබිම්භ සියල්ල" - }, - "mode_observer": { - "message": "නිරීක්ෂකයාට පෙනෙන පරිදි" - }, - "zoom": { - "message": "විශාලනය" - }, - "help": { - "message": "උදව්" - }, - "rayDensity": { - "message": "කිරණ ඝණත්වය" - }, - "raydensity": { - "message": "කිරණ ඝණත්වය" - }, - "undo": { - "message": "Undo" - }, - "redo": { - "message": "Redo" - }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "rename": { - "message": "Rename" - }, - "get_link": { - "message": "Share කිරීමට Link ඒක copy කරන්න." - }, - "export_svg": { - "message": "PNG/SVG ලෙස save කරන්න" - }, - "view_gallery": { - "message": "Gallery බලන්න" - }, - "save_name": { - "message": "නම" - }, - "save_cancel": { - "message": "අවලංගු කරන්න" - }, - "save_description": { - "incomplete": true, - "message": "
  • You may use Settings -> Auto sync URL instead of saving to a file.
  • Click \"Rename\" to change the title without saving to a file.
  • You may consider contribute a new item to the Gallery.
" - }, - "open": { - "message": "විවෘත කරන්න" - }, - "layoutaids": { - "incomplete": true, - "message": "Layout Aids" - }, - "lockObjs": { - "incomplete": true, - "message": "Lock Objects" - }, - "showGrid": { - "message": "Grid" - }, - "snapToGrid": { - "incomplete": true, - "message": "Snap to Grid" - }, - "snaptogrid": { - "incomplete": true, - "message": "Snap to Grid" - }, - "length_unit_popover": { - "incomplete": true, - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "incomplete": true, - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "incomplete": true, - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "incomplete": true, - "message": "Brightness" - }, - "wavelength": { - "message": "තරංග ආයාමය (nm)" - }, - "dichroic": { - "message": "ද්වි වර්ණ" - }, - "filter": { - "message": "පෙරහන" - }, - "bandwidth": { - "message": "Bandwidth (nm)" - }, - "invert": { - "message": "Invert" - }, - "emisAngle": { - "message": "විමෝචන කෝණය (°)" - }, - "mirrored": { - "incomplete": true, - "message": "Mirrored" - }, - "lineDensity": { - "message": "රේඛා/mm" - }, - "slitRatio": { - "message": "ස්ලිට් පළල / රේඛා පරතරය" - }, - "customBrightness": { - "incomplete": true, - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "incomplete": true, - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "message": "සමමිතික" - }, - "eqn_note": { - "incomplete": true, - "message": "
  • Supported constants:
    pi e
  • Supported operators:
    + - * / ^
  • Supported functions:
    sqrt sin cos tan sec csc cot sinh cosh tanh log exp arcsin arccos arctan arcsinh arccosh arctanh floor round ceil trunc sgn max min abs
" - }, - "symbolic_grin": { - "incomplete": true, - "message": "Symbolic body-merging" - }, - "grin_refractive_index": { - "incomplete": true, - "message": "
  • Supported constants:
    pi e
  • Supported operators:
    + - * / ^
  • Supported functions:
    sqrt sin cos tan sec csc cot sinh cosh tanh log arcsin arccos arctan
  • To simulate chromatic dispersion, use parameter lambda for the vacuum wavelength in nanometers.Beta
  • Only supports differentiable functions.
  • The origin of n(x,y) is in the absolute coordinates and does not move with the object. You may double-click a control-point to inspect its absolute coordinates.
  • For a more accurate simulation, see \"More options...\"
" - }, - "symbolic_grin_note_popover": { - "incomplete": true, - "message": "

This toggle applies to all GRIN objects in the simulation.

This simulator has currently two implementations of light propagation between different mediums, for GRIN objects - numerical and symbolic (see 'multRefIndex' and 'devRefIndex' functions in 'CircleGrinGlass.js').

The numerical implementation is faster but doesn't always work properly (depending on the specific case) in scenarios when used with more than one GRIN object, such that at least one of them has a refractive index function which is not defined in the entire plane, while the symbolic implementation is slower but robust to such problems.

" - }, - "focalLength": { - "message": "නාභීය දුර" - }, - "cartesianSign": { - "incomplete": true, - "message": "Cartesian Sign Convention" - }, - "refIndex": { - "message": "වර්තන අංකය*" - }, - "radii_of_curvature": { - "incomplete": true, - "message": "Radii of Curvature" - }, - "focal_distances": { - "message": "නාභීය දුර" - }, - "refIndex_origin": { - "incomplete": true, - "message": "Origin of n(x,y)" - }, - "stepSize": { - "incomplete": true, - "message": "Numerical solver step size" - }, - "intersectTol": { - "incomplete": true, - "message": "Intersection tolerance" - }, - "random": { - "message": "අහඹු" - }, - "lambert": { - "incomplete": true, - "message": "Lambertian" - }, - "diameter": { - "message": "විෂ්කම්භය" - }, - "irradMap": { - "incomplete": true, - "message": "Irradiance Map" - }, - "binSize": { - "incomplete": true, - "message": "Bin Size" - }, - "scaleInterval": { - "message": "පරිමාණ පරතරය" - }, - "exportData": { - "incomplete": true, - "message": "Export data" - }, - "demodulize": { - "incomplete": true, - "message": "Demodulize" - }, - "fontSize": { - "message": "අකුරු ප්‍රමාණය" - }, - "font": { - "message": "අකුරු" - }, - "fontStyle": { - "message": "Style" - }, - "normal": { - "message": "සාමාන්‍ය අකුරු" - }, - "bold": { - "message": "තද අකුරු" - }, - "italic": { - "message": "ඇල අකුරු" - }, - "bolditalic": { - "message": "තද ඇල අකුරු" - }, - "oblique": { - "message": "ආනත අකුරු" - }, - "boldoblique": { - "message": "තද ආනත අකුරු" - }, - "alignment": { - "message": "පෙළගැස්ම" - }, - "left": { - "message": "වම" - }, - "center": { - "message": "මධ්‍ය" - }, - "right": { - "message": "දකුණ" - }, - "text_here": { - "message": "මෙතනින් ලියන්න" - }, - "smallCaps": { - "message": "Small Caps" - }, - "angle": { - "message": "කෝණය (°)" - }, - "arrow": { - "message": "ඉදිරියට ඊතලය" - }, - "backArrow": { - "message": "පසුපසට ඊතලය" - }, - "stop_drawing": { - "message": "ඇඳීම අවසන් කරන්න" - }, - "cropBoxSize": { - "message": "කොටුව crop කරන්න" - }, - "format": { - "message": "ආකෘතිය" - }, - "width": { - "message": "පළල" - }, - "rayCountLimit": { - "message": "කිරණ ගණන සීමාව" - }, - "transformation": { - "incomplete": true, - "message": "TransformationBeta" - }, - "default": { - "incomplete": true, - "message": "Default" - }, - "translation": { - "incomplete": true, - "message": "Translation" - }, - "xTranslation": { - "incomplete": true, - "message": "X Translation" - }, - "yTranslation": { - "incomplete": true, - "message": "Y Translation" - }, - "rotation": { - "incomplete": true, - "message": "Rotation" - }, - "scaling": { - "incomplete": true, - "message": "Scaling" - }, - "beam_warning": { - "message": "අපසාරී/අහඹු කදම්භ සමඟ ප්‍රතිබිම්භ හඳුනාගැනීම ක්‍රියා නොකරයි." - }, - "image_detection_warning": { - "message": "මෙම මෙවලම ප්‍රතිබිම්භ හඳුනා ගැනීමට සහාය නොදක්වයි." - }, - "non_simulateColors_warning": { - "message": "මෙම මෙවලම ක්‍රියා කරන්නේ \"වර්ණ අනුකරණය\" ක්‍රියාත්මක විට පමණි." - }, - "brightness_note_popover": { - "message": "

'කිරණ ඝනත්වය' ප්‍රමාණවත් තරම් ඉහළ නම් පමණක් ඵලදායී වේ.

විමෝචනය වන කිරණ සංඛ්‍යාව පාලනය කිරීමට, කරුණාකර ගෝලීය 'කිරණ ඝනත්වය' ස්ලයිඩරය සීරුමාරු කරන්න.

" - }, - "refIndex_note_popover": { - "message": "

*වෙනත් වීදුරුවක් ඇතුළත නම් සාපේක්ෂ

මෙම වස්තුව (නිරපේක්ෂ) වර්තන දර්ශකය n₁ සමඟ අනුකරණය කළ යුතු නමුත්, වර්තන දර්ශකය n₀ සහිත වෙනත් වීදුරුවක් තුළ තබා තිබේ නම්, ඔබ මෙහි වර්තන දර්ශකය n₁/n₀ ලෙස සැකසිය යුතුය. වීදුරු කිහිපයක් එකට අතිච්ඡාදනය වන වඩාත් සංකීර්ණ අවස්ථාවන්හිදී, අතිච්ඡාදනය වන කලාපයේ ඵලදායී පරාවර්තක දර්ශකය එක් එක් ඒවායේ පරාවර්තක දර්ශකවල ගුණිතයට සමාන වේ.

" - }, - "stepSize_note_popover": { - "incomplete": true, - "message": "

Step size of Euler's method for solving the eikonal ray equation - see 'step' function and documentation inside the 'CircleGrinGlass.js' file, for more information.

" - }, - "eps_CircleGrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length]^2.

This numerical tolerance is used in the functions 'isOutsideGlass', 'isInsideGlass' and 'isOnBoundary', inside the 'CircleGrinGlass.js' file.

" - }, - "eps_GrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length].

This numerical tolerance is used in the functions 'isOnBoundary' and 'countIntersections', inside the 'GrinGlass.js' file.

" - }, - "cauchyCoeff": { - "message": "Cauchy සංගුණකය" - }, - "transRatio": { - "message": "සම්ප්‍රේෂණ අනුපාතය" - }, - "applytoall": { - "message": "සියල්ලටම අයදුම් කරන්න" - }, - "duplicate": { - "message": "අනුපිටපත් කරන්න" - }, - "delete": { - "message": "මකන්න" - }, - "unselect": { - "message": "තේරීම ඉවත් කරන්න" - }, - "unselect_popover": { - "message": "මෙම වස්තුව තේරීමෙන් ඉවත් කරන්න (හිස් අවකාශය මත දකුණු-ක්ලික් කීරීමෙන්ද කළ හැක)" - }, - "showadvanced": { - "message": "තවත් විකල්පයන්..." - }, - "processing": { - "message": "සකසමින්... නතර කිරීමට මෙතන click කරන්න." - }, - "contribute": { - "message": "දායක වන්න" - }, - "github": { - "message": "GitHub" - }, - "about": { - "message": "මේ පිළිබඳව" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "message": "මෙම යෙදුම පරිවර්තනය කිරීමට අපට උදවු කරන්න" - }, - "translated": { - "message": "පරිවර්තිතයි" - }, - "undo_popover": { - "message": "Undo කරන්න. (Ctrl+Z)" - }, - "redo_popover": { - "message": "Redo කරන්න. (Ctrl+Y)" - }, - "reset_popover": { - "message": "සියලු වෙනස්කම් Reset කරන්න." - }, - "save_popover": { - "message": "වත්මන් දර්ශනය ගොනුවක්(file) ලෙස සුරකින්න." - }, - "open_popover": { - "incomplete": true, - "message": "Open an existing file or background image. The background image will be shown from the coordinate origin. (Or drop the file)" - }, - "get_link_popover": { - "incomplete": true, - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "incomplete": true, - "message": "The URL is too long that it may not work on some platforms. You may need to use \"Save\" and share the file instead." - }, - "export_svg_warning": { - "incomplete": true, - "message": "Export to SVG: Color mixtures and relative refractive indices below 1 are not supported." - }, - "export_ray_count_warning": { - "incomplete": true, - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "message": "උදාහරණ සදහා Galleryට යන්න." - }, - "tool_SingleRay_popover": { - "message": "ලක්ෂ්‍යය දෙකකින් අර්ථ දක්වා ඇති තනි ආලෝක කිරණකි. (නිර්මාණය කිරීමට drag හෝ click කරන්න. පළමු ලක්ෂ්‍යය ප්‍රභවය ද, දෙවන ලක්ෂ්‍යය කිරණයේ දිශාව ද වේ.)" - }, - "tool_Beam_popover": { - "message": "රේඛීය සමාන්තර හෝ අපසාරී කිරණ කදම්භයක් මතු වන අතර 'කිරණ ඝනත්වය' slider මගින් ඝනත්වය පාලනය කරයි. (නිර්මාණය කිරීමට drag හෝ click කරන්න.)" - }, - "tool_PointSource_popover": { - "message": "එක් ලක්ෂ්‍යයකින් කිරණ මතු වේ.'කිරණ ඝනත්වය' slider මඟින් සංඛ්‍යාව පාලනය වේ.(නිර්මාණය කිරීමට click කරන්න.)" - }, - "tool_AngleSource_popover": { - "message": "දී ඇති විමෝචන කෝණයක් සහිත ලක්ෂ්‍යය ප්‍රභවක්." - }, - "tool_Mirror_popover": { - "message": "දර්පණයක් මත ආලෝකයේ පරාවර්තනය අනුකරණය (simulate) කරන්න. (නිර්මාණය කිරීමට drag හෝ click කරන්න.)" - }, - "tool_ArcMirror_popover": { - "message": "ලක්ෂ්‍ය තුනකින් අර්ථ දක්වා ඇති රවුමක කොටසක් වන දර්පණයක්. (නිර්මාණය කිරීමට drag හෝ click කරන්න. පළමු ලක්ෂ්‍යය 2 චාපයේ දාර අතර පරතරය නිරූපණය කරයි, අවසාන ලක්ෂ්‍යය චාපයේ විශාලත්වය නිරූපණය කරයි.)" - }, - "tool_ParabolicMirror_popover": { - "message": "ලක්ෂ්‍ය තුනකින් අර්ථ දක්වා ඇති පැරබෝලා හැඩයක් ඇති කැඩපතකි. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_CustomMirror_popover": { - "message": "අභිරුචි සමීකරණයකින් y = f(x) හැඩය නිර්වචනය කරන ලද කැඩපතක්, එහිදී (x,y) පාලන ලක්ෂ්‍ය දෙක (-1,0) සහ (1,0) වන පරිණාමනය වූ ඛණ්ඩාංකවල ඇත. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_BeamSplitter_popover": { - "message": "එන ආලෝකයේ ප්‍රතිශතයක් සම්ප්‍රේෂණය කරන කැඩපතක්. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_IdealMirror_popover": { - "message": "(1/p + 1/q = 1/f) දර්පණ සමීකරණයට ඒකග වන දර්ශීය 'වක්‍ර' දර්පණය. නාභීය දුර සෘජුවම සැකසිය හැක. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_PlaneGlass_popover": { - "message": "පෘෂ්ඨයක් මත ආලෝකයේ වර්තනය සහ පරාවර්තනය අනුකරණය කරන්න. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_CircleGlass_popover": { - "message": "රවුම් හැඩයක් සහිත වීදුරු, එහි කේන්ද්‍රය සහ මතුපිට ලක්ෂ්‍යයක් මගින් අර්ථ දක්වා ඇත. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_CircleGrinGlass_popover": { - "message": "අභිරුචි වර්තන දර්ශක ශ්‍රිතයක් n(x,y) සහ චක්‍ර මායිමක් සහිත වීදුරු. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_Glass_popover": { - "message": "රේඛා කොටස් සහ වෘත්තාකාර චාප වලින් සාදන ලද ඕනෑම හැඩයක් සහිත වීදුරු. (කොටසක් සෑදීමට ක්ලික් කරන්න, චාපයක් සෑදීමට අදින්න, ඇඳීම අවසන් කරන විට ආරම්භක ස්ථානය මත ක්ලික් කරන්න.)" - }, - "tool_GrinGlass_popover": { - "message": "අභිරුචි වර්තන දර්ශක ශ්‍රිතයක් n(x,y) සහ බහුඅස්‍ර මායිමක් සහිත වීදුරු. අවවාදයයි: සරල බහුඅස්ර පමණක් සහාය දක්වයි, එසේ නොමැති නම් හැසිරීම අනපේක්ෂිත වේ. (කොටසක් සෑදීමට ක්ලික් කරන්න, ඇඳීම අවසන් වන විට ආරම්භක ස්ථානය මත ක්ලික් කරන්න.)" - }, - "tool_IdealLens_popover": { - "message": "සිහින් කාච සමීකරණයට (1/p + 1/q = 1/f) අවනත වන දර්ශීය කාචයකි. නාභීය දුර සෘජුවම සැකසිය හැක. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_SphericalLens_popover": { - "message": "ගෝලාකාර කාචයක්. (නිර්මාණය කිරීමට ක්ලික් කරන්න.)" - }, - "tool_CustomGlass_popover": { - "message": "අභිරුචි අසමානතාවයකින් අර්ථ දක්වා ඇති හැඩය සහිත වීදුරු f(x) < y < g(x), (x,y) යනු පාලන ලක්ෂ්‍ය දෙක (-1,0) සහ (1,0) වන පරිණාමනය කරන ලද ඛණ්ඩාංකවල ඇත. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_Blocker_popover": { - "message": "රේඛීය ආලෝක අවහිරකයක්. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_Aperture_popover": { - "message": "ආලෝක අවහිරක යුගලයක්. කුහරයේ විශාලත්වය සමමිතිකව සකස් කළ හැක. (නිර්මාණය කිරීමට අන්ත ලක්ෂ්‍ය දෙක අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_CircleBlocker_popover": { - "message": "රවුම් ආලෝකය අවහිරකයක්. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_DiffractionGrating_popover": { - "message": "තරංග ආයාමය මත විවිධ කෝණවලින් ආලෝකය වර්තන කරන විවර්තන තලයක්. අවවාදයයි: විවර්තන කිරණවල තීව්‍රතාවය නිවැරදි නොවිය හැක. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_Ruler_popover": { - "message": "පරිමාණය ඇති රූලක්. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_Protractor_popover": { - "message": "පරිමාණය අංශක වලින් ඇති කෝණමානයක්. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_Detector_popover": { - "message": "ශක්ති ප්‍රවාහයේ වේගය (P), ලම්බක ගම්‍යතා ප්‍රවාහයේ වේගය (F⊥) සහ රේඛා ඛණ්ඩයක් හරහා සමාන්තර ගම්‍යතා ප්‍රවාහයේ වේගය (F∥) මැනීම සඳහා මෙවලමකි. (රේඛා ඛණ්ඩය සෑදීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_Detector_info_popover": { - "incomplete": true, - "message": "
  • P: The rate of energy flow (flux) in B/s (see below).
  • F⊥: The rate of perpendicular momentum flow in (B/s)/c.
  • F∥: The rate of parallel momentum flow in (B/s)/c.
  • The irradiance in the exported CSV is in (B/s)/L.
  • L is the arbitrary unit of length used in this simulator.
  • B is an arbitrary unit of radiant flux or luminous flux, corresponding to the unit of the \"Brightness\" option being B/L for non-Lambertian beams and 500B/360° for point sources.
  • The dimensionless factor s is the \"Brightness Scale\" shown in Settings -> Show status box, which equals 1 when \"Ray Density\" is above some threshold and proportional to \"Ray Density\" otherwise.
  • If some rays are truncated in the infinite series of internal reflection, the total truncation is shown as error estimates.
" - }, - "tool_TextLabel_popover": { - "incomplete": true, - "message": "A text label." - }, - "tool_LineArrow_popover": { - "message": "රේඛා ඛණ්ඩයක් හෝ ඊතලයක්. (නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න.)" - }, - "tool_Drawing_popover": { - "message": "නිදහස් අතින් ඇඳීමේ මෙවලමක්. (ඇඳීමට ඇදගෙන යන්න.)" - }, - "tool__popover": { - "message": "දසුන ගෙනයාමට අදින්න. (Mouse right button dragට සමානවේ.)" - }, - "mode_rays_popover": { - "message": "කිරණ පෙන්වන්න. 'කිරණ ඝනත්වය' වැඩි වූ විට ඒවා අඛණ්ඩව පවතින බව පෙනේ." - }, - "mode_extended_popover": { - "message": "කිරණ සහ එහි දිගු දෙකම පෙන්වන්න. තැඹිලි මගින් පසුගාමී දිගුවන් සහ අළු යනු මගින් ඉදිරි දිගුවන් පෙන්නුම් කරයි
'වර්ණ අනුකරණය' සක්‍රීය කර ඇති විට, ඒවා ප්‍රභව වර්ණවලින් පෙන්වයි." - }, - "mode_images_popover": { - "message": "සියලුම ප්‍රතිබිම්භ පිහිටීම පෙන්වන්න. කහ පැහැති ලක්ෂ්‍ය තාත්වික ප්‍රතිබිම්භ ද, තැඹිලි පැහැයෙන් අතාත්වික ප්‍රතිබිම්භ ද, අළු (මෙම පින්තූරයේ කිසිවක් නැත) අථත්‍ය වස්තු ද දක්වයි. 'කිරණ ඝනත්වය' ප්‍රමාණවත් නොවේ නම් සමහර පින්තූර අනාවරණය කර ගත නොහැකි බව සලකන්න.
'වර්ණ අනුකරණය' ක්‍රියාත්මක වන විට, ඒවා ප්‍රභව වර්ණවලින් පෙන්වන අතර ඒ වෙනුවට තිත් ප්‍රමාණයෙන් වෙන්කර හඳුනා ගනී." - }, - "mode_observer_popover": { - "message": "යම් ස්ථානයක සිට දකින කිරණ සහ රූප අනුකරණය කරන්න. නිල් කවය නිරීක්ෂකයා වේ. එය හරහා යන ඕනෑම කිරණ 'නිරීක්ෂණය' ලෙස සැලකේ. කිරණ ඇත්ත වශයෙන්ම ආරම්භ වන්නේ කොතැනින්ද යන්න නිරීක්ෂකයා නොදනී, නමුත් ඒවා යම් ස්ථානයක ඡේදනය වුවහොත් ඒවා ආරම්භ වන්නේ යැයි සිතිය හැකිය. කිරණ නිල් පැහැයෙන් ද, ලක්ෂ්‍ය කහ (තාත්වික ප්‍රතිබිම්භ) හෝ තැඹිලි (අතාත්වික ප්‍රතිබිම්භ) ලෙස ද දැක්වේ. (නිරීක්ෂකයා ගෙන යාමට විශාල නිල් තිත අදින්න.)
'වර්ණ අනුකරණය' ක්‍රියාත්මක විට, ඒ වෙනුවට ඒවා ප්‍රභව වර්ණවලින් පෙන්වනු ලැබේ." - }, - "simulateColors_popover": { - "incomplete": true, - "message": "Simulate colors (wavelengths) of light sources, mixture of colors, color filtering of blockers and mirrors, and chromatic dispersion of glasses. You can set those parameters for those objects when selected. To simulate color spectra, overlap rays with different wavelengths. The colors shown on the screen are only rough approximations, and can be very inaccurate when 'Ray density' is too high or too low." - }, - "rayDensity_popover": { - "message": "කදම්භ සහ ලක්ෂ්‍ය මූලාශ්‍ර මගින් විමෝචනය කළ යුතු කිරණ ගණන තීරණය කරයි. මෙය රූප හඳුනාගැනීමේ සහ වර්ණ විදැහුම්කරණයේ නිරවද්‍යතාවයට ද බලපායි." - }, - "showGrid_popover": { - "message": "පසුබිම් ජාලයේ දෘශ්‍යතාව නිර්ණය." - }, - "grid_popover": { - "message": "Grid එකට snap කළ යුතුද යන්න නිර්ණය." - }, - "lockObjs_popover": { - "message": "වස්තු චලනය කළ හැකිද නැද්ද යන්න නිර්ණය." - }, - "zoom_popover": { - "message": "දර්ශනය ප්‍රතිශතයක් සමඟ විශාලනය කරන්න." - }, - "help_popover": { - "incomplete": true, - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "message": "උදවු popup පෙන්වන්න" - }, - "show_help_popups_popover": { - "message": "බොත්තම් මත සැරිසරන විට උපකාර popup පෙන්විය යුතුද යන්න නිර්ණය. (බලපෑමට පිටුව refresh කරන්න.)" - }, - "show_json_editor": { - "message": "JSON editor පෙන්වන්නBeta" - }, - "show_json_editor_popover": { - "incomplete": true, - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "message": "Status box පෙන්වන්න" - }, - "show_status_popover": { - "incomplete": true, - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "incomplete": true, - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "incomplete": true, - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "incomplete": true, - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "message": "ජාලක ප්‍රමාණය" - }, - "observer_size": { - "message": "නිරීක්ෂකයාගේ ප්‍රමාණය" - }, - "language": { - "message": "භාෂාව" - }, - "close": { - "message": "වසන්න" - }, - "advanced_help": { - "message": "වැඩිදුර උදව් සඳහා, පහළ-දකුණු කෙළවරේ ඇති help icon බලන්න." - }, - "ray_count": { - "message": "කිරණ කොටස් සංඛ්‍යාව: " - }, - "total_truncation": { - "message": "කපා දැමූ දීප්තිය: " - }, - "brightness_scale": { - "incomplete": true, - "message": "Brightness Scale: " - }, - "time_elapsed": { - "message": "ගතවූ කාලය (ms): " - }, - "force_stopped": { - "message": "බලහත්කාරයෙන් නතර විය." - }, - "mouse_coordinates": { - "message": "Mouse ඛණ්ඩාංක: " - }, - "modules_tutorial": { - "incomplete": true, - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "message": "දර්ශනයේ සම්පූර්ණයෙන්ම අතිච්ඡාදනය වන සමාන දෘශ්‍ය මූලද්‍රව්‍ය දෙකක් ඇත." - }, - "import_modules": { - "message": "Import Modules..." - }, - "import_modules_title": { - "message": "Import Modules" - }, - "modules_url": { - "message": "../modules/modules.html" - }, - "remove_module": { - "message": "module ඉවත් කරන්න" - }, - "module_conflict": { - "incomplete": true, - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "incomplete": true, - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/si/main.json b/locales/si/main.json new file mode 100644 index 00000000..8e6c29d1 --- /dev/null +++ b/locales/si/main.json @@ -0,0 +1,206 @@ +{ + "meta": { + "languageName": "සිංහල", + "parentheses": "{{main}} ({{sub}})", + "colon": "{{name}}: {{value}}", + "list": "{{first}}, {{others}}" + }, + "project": { + "name": "Ray Optics Simulation", + "shortName": "Ray Optics", + "description": "ද්විමාන ප්‍රකාශ(ආලෝක) දර්ශන නිර්මාණය කිරීම simulate කිරීම සඳහා free, open-source වෙබ් යෙදුමකි." + }, + "pages": { + "simulator": "Simulator", + "home": "මුල් පිටුව", + "gallery": "Gallery", + "about": "මේ පිළිබඳව", + "github": "GitHub" + }, + "homePage": { + "launchSimulator": "Simulator Launch කරන්න." + }, + "tools": { + "categories": { + "lightSource": "ආලෝක ප්‍රභවයන්", + "mirror": "දර්පණ", + "glass": "වීදුරු", + "blocker": "බාධක", + "other": "අමතර" + }, + "common": { + "clickInstruction": "නිර්මාණය කිරීමට click කරන්න.", + "lineInstruction": "නිර්මාණය කිරීමට drag හෝ click කරන්න.", + "circleInstruction": "නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න." + }, + "SingleRay": { + "title": "තනි ආලෝක කිරණයක්", + "description": "ලක්ෂ්‍යය දෙකකින් අර්ථ දක්වා ඇති තනි ආලෝක කිරණකි.", + "instruction": "නිර්මාණය කිරීමට drag හෝ click කරන්න. පළමු ලක්ෂ්‍යය ප්‍රභවය ද, දෙවන ලක්ෂ්‍යය කිරණයේ දිශාව ද වේ." + }, + "Beam": { + "title": "ආලෝක කදම්භය", + "description": "රේඛීය සමාන්තර හෝ අපසාරී කිරණ කදම්භයක් මතු වන අතර 'කිරණ ඝනත්වය' slider මගින් ඝනත්වය පාලනය කරයි." + }, + "PointSource": { + "title": "ආලෝක ප්‍රභවය", + "description": "එක් ලක්ෂ්‍යයකින් කිරණ මතු වේ.'කිරණ ඝනත්වය' slider මඟින් සංඛ්‍යාව පාලනය වේ." + }, + "AngleSource": { + "instruction": "නිර්මාණය කිරීමට drag හෝ click කරන්න. පළමු ලක්ෂ්‍යය ප්‍රභවය ද, දෙවන ලක්ෂ්‍යය කිරණයේ දිශාව ද වේ.", + "description": "දී ඇති විමෝචන කෝණයක් සහිත ලක්ෂ්‍යය ප්‍රභවක්." + }, + "Mirror": { + "title": "කොටසක්", + "description": "දර්පණයක් මත ආලෝකයේ පරාවර්තනය අනුකරණය (simulate) කරන්න." + }, + "otherMirror": { + "title": "Custom සමීකරණ", + "description": "අභිරුචි සමීකරණයකින් y = f(x) හැඩය නිර්වචනය කරන ලද කැඩපතක්, එහිදී (x,y) පාලන ලක්ෂ්‍ය දෙක (-1,0) සහ (1,0) වන පරිණාමනය වූ ඛණ්ඩාංකවල ඇත." + }, + "ArcMirror": { + "title": "වෘත්තාකාර චාප", + "description": "ලක්ෂ්‍ය තුනකින් අර්ථ දක්වා ඇති රවුමක කොටසක් වන දර්පණයක්.", + "instruction": "නිර්මාණය කිරීමට drag හෝ click කරන්න. පළමු ලක්ෂ්‍යය 2 චාපයේ දාර අතර පරතරය නිරූපණය කරයි, අවසාන ලක්ෂ්‍යය චාපයේ විශාලත්වය නිරූපණය කරයි." + }, + "ParabolicMirror": { + "title": "පරාවලයික", + "description": "ලක්ෂ්‍ය තුනකින් අර්ථ දක්වා ඇති පැරබෝලා හැඩයක් ඇති කැඩපතකි.", + "instruction": "නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න." + }, + "CustomMirror": { + "title": "Custom සමීකරණ", + "description": "අභිරුචි සමීකරණයකින් y = f(x) හැඩය නිර්වචනය කරන ලද කැඩපතක්, එහිදී (x,y) පාලන ලක්ෂ්‍ය දෙක (-1,0) සහ (1,0) වන පරිණාමනය වූ ඛණ්ඩාංකවල ඇත." + }, + "IdealMirror": { + "title": "පරිපූර්ණ වක්‍ර", + "description": "(1/p + 1/q = 1/f) දර්පණ සමීකරණයට ඒකග වන දර්ශීය 'වක්‍ර' දර්පණය. නාභීය දුර සෘජුවම සැකසිය හැක." + }, + "BeamSplitter": { + "title": "කදම්භ විබෙදුම", + "description": "එන ආලෝකයේ ප්‍රතිශතයක් සම්ප්‍රේෂණය කරන කැඩපතක්." + }, + "PlaneGlass": { + "title": "අර්ධ තලයක්", + "description": "පෘෂ්ඨයක් මත ආලෝකයේ වර්තනය සහ පරාවර්තනය අනුකරණය කරන්න.", + "instruction": "නිර්මාණය කිරීමට අදින්න හෝ ක්ලික් කරන්න." + }, + "otherGlass": { + "title": "Custom සමීකරණ", + "description": "අභිරුචි අසමානතාවයකින් අර්ථ දක්වා ඇති හැඩය සහිත වීදුරු f(x) < y < g(x), (x,y) යනු පාලන ලක්ෂ්‍ය දෙක (-1,0) සහ (1,0) වන පරිණාමනය කරන ලද ඛණ්ඩාංකවල ඇත." + }, + "CircleGlass": { + "title": "වෘත්ත", + "description": "රවුම් හැඩයක් සහිත වීදුරු, එහි කේන්ද්‍රය සහ මතුපිට ලක්ෂ්‍යයක් මගින් අර්ථ දක්වා ඇත." + }, + "Glass": { + "description": "රේඛා කොටස් සහ වෘත්තාකාර චාප වලින් සාදන ලද ඕනෑම හැඩයක් සහිත වීදුරු.", + "instruction": "කොටසක් සෑදීමට ක්ලික් කරන්න, චාපයක් සෑදීමට අදින්න, ඇඳීම අවසන් කරන විට ආරම්භක ස්ථානය මත ක්ලික් කරන්න." + }, + "CustomGlass": { + "title": "Custom සමීකරණ", + "description": "අභිරුචි අසමානතාවයකින් අර්ථ දක්වා ඇති හැඩය සහිත වීදුරු f(x) < y < g(x), (x,y) යනු පාලන ලක්ෂ්‍ය දෙක (-1,0) සහ (1,0) වන පරිණාමනය කරන ලද ඛණ්ඩාංකවල ඇත." + }, + "IdealLens": { + "title": "පරිපූර්ණ කාච", + "description": "සිහින් කාච සමීකරණයට (1/p + 1/q = 1/f) අවනත වන දර්ශීය කාචයකි. නාභීය දුර සෘජුවම සැකසිය හැක." + }, + "SphericalLens": { + "title": "වක්‍ර කාච", + "description": "ගෝලාකාර කාචයක්." + }, + "CircleGrinGlass": { + "title": "අනුක්‍රමිකව වර්තනාංකය වෙනස් වන වෘත්තාකාර වීදුරුව", + "description": "අභිරුචි වර්තන දර්ශක ශ්‍රිතයක් n(x,y) සහ චක්‍ර මායිමක් සහිත වීදුරු." + }, + "GrinGlass": { + "title": "අනුක්‍රමිකව වර්තනාංකය වෙනස් වන බහුඅස්‍ර", + "description": "අභිරුචි වර්තන දර්ශක ශ්‍රිතයක් n(x,y) සහ බහුඅස්‍ර මායිමක් සහිත වීදුරු.", + "instruction": "කොටසක් සෑදීමට ක්ලික් කරන්න, ඇඳීම අවසන් වන විට ආරම්භක ස්ථානය මත ක්ලික් කරන්න.", + "warning": "අවවාදයයි: සරල බහුඅස්ර පමණක් සහාය දක්වයි, එසේ නොමැති නම් හැසිරීම අනපේක්ෂිත වේ." + }, + "otherGrinGlass": { + "title": "අනුක්‍රමිකව වර්තනාංකය වෙනස් වන වීදුරු" + }, + "Blocker": { + "title": "‌රේඛීය බාධක", + "description": "රේඛීය ආලෝක අවහිරකයක්." + }, + "CircleBlocker": { + "title": "වක්‍ර බාධක", + "description": "රවුම් ආලෝකය අවහිරකයක්." + }, + "Aperture": { + "title": "විවරය", + "description": "ආලෝක අවහිරක යුගලයක්. කුහරයේ විශාලත්වය සමමිතිකව සකස් කළ හැක.", + "instruction": "නිර්මාණය කිරීමට අන්ත ලක්ෂ්‍ය දෙක අදින්න හෝ ක්ලික් කරන්න." + }, + "DiffractionGrating": { + "title": "විවර්තන තලය", + "description": "තරංග ආයාමය මත විවිධ කෝණවලින් ආලෝකය වර්තන කරන විවර්තන තලයක්.", + "warning": "අවවාදයයි: විවර්තන කිරණවල තීව්‍රතාවය නිවැරදි නොවිය හැක." + }, + "Ruler": { + "title": "රූල", + "description": "පරිමාණය ඇති රූලක්." + }, + "Protractor": { + "title": "කෝණමානය", + "description": "පරිමාණය අංශක වලින් ඇති කෝණමානයක්." + }, + "Detector": { + "title": "අනාවරකය", + "description": "ශක්ති ප්‍රවාහයේ වේගය (P), ලම්බක ගම්‍යතා ප්‍රවාහයේ වේගය (F⊥) සහ රේඛා ඛණ්ඩයක් හරහා සමාන්තර ගම්‍යතා ප්‍රවාහයේ වේගය (F∥) මැනීම සඳහා මෙවලමකි." + }, + "TextLabel": { + "title": "Text" + }, + "LineArrow": { + "title": "රේඛා / ඊතල", + "description": "රේඛා ඛණ්ඩයක් හෝ ඊතලයක්." + }, + "Drawing": { + "title": "Drawing", + "description": "නිදහස් අතින් ඇඳීමේ මෙවලමක්.", + "instruction": "ඇඳීමට ඇදගෙන යන්න." + }, + "moveView": { + "title": "Move view", + "description": "දසුන ගෙනයාමට අදින්න. (Mouse right button dragට සමානවේ.)" + }, + "modules": { + "import": "Import Modules...", + "remove": "module ඉවත් කරන්න" + } + }, + "view": { + "title": "View", + "rays": { + "title": "කිරණ", + "description": "කිරණ පෙන්වන්න. 'කිරණ ඝනත්වය' වැඩි වූ විට ඒවා අඛණ්ඩව පවතින බව පෙනේ." + }, + "extended": { + "title": "දිගුකල කිරණ", + "description": "කිරණ සහ එහි දිගු දෙකම පෙන්වන්න. තැඹිලි මගින් පසුගාමී දිගුවන් සහ අළු යනු මගින් ඉදිරි දිගුවන් පෙන්නුම් කරයි", + "simulateColorsNote": "'වර්ණ අනුකරණය' සක්‍රීය කර ඇති විට, ඒවා ප්‍රභව වර්ණවලින් පෙන්වයි." + }, + "images": { + "title": "ප්‍රතිබිම්භ සියල්ල", + "description": "සියලුම ප්‍රතිබිම්භ පිහිටීම පෙන්වන්න. කහ පැහැති ලක්ෂ්‍ය තාත්වික ප්‍රතිබිම්භ ද, තැඹිලි පැහැයෙන් අතාත්වික ප්‍රතිබිම්භ ද, අළු (මෙම පින්තූරයේ කිසිවක් නැත) අථත්‍ය වස්තු ද දක්වයි. 'කිරණ ඝනත්වය' ප්‍රමාණවත් නොවේ නම් සමහර පින්තූර අනාවරණය කර ගත නොහැකි බව සලකන්න.", + "simulateColorsNote": "'වර්ණ අනුකරණය' ක්‍රියාත්මක වන විට, ඒවා ප්‍රභව වර්ණවලින් පෙන්වන අතර ඒ වෙනුවට තිත් ප්‍රමාණයෙන් වෙන්කර හඳුනා ගනී." + }, + "observer": { + "title": "නිරීක්ෂකයාට පෙනෙන පරිදි", + "description": "යම් ස්ථානයක සිට දකින කිරණ සහ රූප අනුකරණය කරන්න. නිල් කවය නිරීක්ෂකයා වේ. එය හරහා යන ඕනෑම කිරණ 'නිරීක්ෂණය' ලෙස සැලකේ. කිරණ ඇත්ත වශයෙන්ම ආරම්භ වන්නේ කොතැනින්ද යන්න නිරීක්ෂකයා නොදනී, නමුත් ඒවා යම් ස්ථානයක ඡේදනය වුවහොත් ඒවා ආරම්භ වන්නේ යැයි සිතිය හැකිය. කිරණ නිල් පැහැයෙන් ද, ලක්ෂ්‍ය කහ (තාත්වික ප්‍රතිබිම්භ) හෝ තැඹිලි (අතාත්වික ප්‍රතිබිම්භ) ලෙස ද දැක්වේ.", + "simulateColorsNote": "'වර්ණ අනුකරණය' ක්‍රියාත්මක විට, ඒ වෙනුවට ඒවා ප්‍රභව වර්ණවලින් පෙන්වනු ලැබේ.", + "instruction": "නිරීක්ෂකයා ගෙන යාමට විශාල නිල් තිත අදින්න." + } + }, + "simulateColors": { + "title": "වර්ණ අනුකරණය" + }, + "languageDropdown": { + "title": "භාෂාව: {{language}}", + "translatedFraction": "{{fraction}} පරිවර්තිතයි" + } +} \ No newline at end of file diff --git a/locales/si/simulator.json b/locales/si/simulator.json new file mode 100644 index 00000000..fb52adb1 --- /dev/null +++ b/locales/si/simulator.json @@ -0,0 +1,207 @@ +{ + "welcome": { + "title": "Ray Optics Simulation වෙත සාදරයෙන් පිළිගනිමු", + "instruction": "optical component එක් කිරීමට tool තෝරා හිස් අවකාශය මත click කරන්න.\nඋදාහරණ සඳහා [Gallery page වෙත යන්න](/gallery).", + "loading": "URL වෙතින් දර්ශනය load වේ... කරුණාකර රැඳී සිටින්න." + }, + "common": { + "saveButton": "Save", + "cancelButton": "අවලංගු කරන්න", + "closeButton": "වසන්න" + }, + "file": { + "undo": { + "title": "Undo" + }, + "redo": { + "title": "Redo" + }, + "reset": { + "title": "Reset" + }, + "save": { + "title": "Save" + }, + "open": { + "title": "විවෘත කරන්න" + }, + "export": { + "title": "PNG/SVG ලෙස save කරන්න" + }, + "copyLink": { + "title": "Share කිරීමට Link ඒක copy කරන්න." + }, + "viewGallery": { + "title": "Gallery බලන්න", + "description": "උදාහරණ සදහා Galleryට යන්න." + } + }, + "settings": { + "title": "සැකසුම්", + "more": "තවත්", + "rayDensity": { + "title": "කිරණ ඝණත්වය", + "description": "කදම්භ සහ ලක්ෂ්‍ය මූලාශ්‍ර මගින් විමෝචනය කළ යුතු කිරණ ගණන තීරණය කරයි. මෙය රූප හඳුනාගැනීමේ සහ වර්ණ විදැහුම්කරණයේ නිරවද්‍යතාවයට ද බලපායි." + }, + "layoutAids": { + "showGrid": "Grid" + }, + "gridSize": { + "title": "ජාලක ප්‍රමාණය" + }, + "observerSize": { + "title": "නිරීක්ෂකයාගේ ප්‍රමාණය" + }, + "zoom": { + "title": "විශාලනය" + }, + "language": { + "title": "භාෂාව" + }, + "showJsonEditor": { + "title": "JSON editor පෙන්වන්න" + }, + "showStatusBox": { + "title": "Status box පෙන්වන්න" + }, + "showHelpPopups": { + "title": "උදවු popup පෙන්වන්න", + "description": "බොත්තම් මත සැරිසරන විට උපකාර popup පෙන්විය යුතුද යන්න නිර්ණය. (බලපෑමට පිටුව refresh කරන්න.)" + }, + "advancedHelp": "වැඩිදුර උදව් සඳහා, පහළ-දකුණු කෙළවරේ ඇති help icon බලන්න." + }, + "objBar": { + "showAdvanced": { + "title": "තවත් විකල්පයන්..." + }, + "applyToAll": { + "title": "සියල්ලටම අයදුම් කරන්න" + }, + "duplicate": { + "title": "අනුපිටපත් කරන්න" + }, + "delete": { + "title": "මකන්න" + }, + "unselect": { + "title": "තේරීම ඉවත් කරන්න", + "description": "මෙම වස්තුව තේරීමෙන් ඉවත් කරන්න (හිස් අවකාශය මත දකුණු-ක්ලික් කීරීමෙන්ද කළ හැක)" + } + }, + "sceneObjs": { + "common": { + "brightnessInfo": { + "rayDensity": "'කිරණ ඝනත්වය' ප්‍රමාණවත් තරම් ඉහළ නම් පමණක් ඵලදායී වේ.", + "rayDensitySlider": "විමෝචනය වන කිරණ සංඛ්‍යාව පාලනය කිරීමට, කරුණාකර ගෝලීය 'කිරණ ඝනත්වය' ස්ලයිඩරය සීරුමාරු කරන්න." + }, + "wavelength": "තරංග ආයාමය", + "emisAngle": "විමෝචන කෝණය", + "random": "අහඹු", + "focalLength": "නාභීය දුර", + "imageDetectionWarning": "මෙම මෙවලම ප්‍රතිබිම්භ හඳුනා ගැනීමට සහාය නොදක්වයි.", + "nonSimulateColorsWarning": "මෙම මෙවලම ක්‍රියා කරන්නේ \"වර්ණ අනුකරණය\" ක්‍රියාත්මක විට පමණි." + }, + "Beam": { + "imageDetectionWarning": "අපසාරී/අහඹු කදම්භ සමඟ ප්‍රතිබිම්භ හඳුනාගැනීම ක්‍රියා නොකරයි." + }, + "AngleSource": { + "symmetric": "සමමිතික" + }, + "BaseFilter": { + "filter": "පෙරහන", + "bandwidth": "Bandwidth", + "invert": "Invert" + }, + "BeamSplitter": { + "transRatio": "සම්ප්‍රේෂණ අනුපාතය" + }, + "BaseGlass": { + "refIndex": "වර්තන අංකය", + "refIndexInfo": { + "relative": "වෙනත් වීදුරුවක් ඇතුළත නම් සාපේක්ෂ", + "effective": "මෙම වස්තුව (නිරපේක්ෂ) වර්තන දර්ශකය n₁ සමඟ අනුකරණය කළ යුතු නමුත්, වර්තන දර්ශකය n₀ සහිත වෙනත් වීදුරුවක් තුළ තබා තිබේ නම්, ඔබ මෙහි වර්තන දර්ශකය n₁/n₀ ලෙස සැකසිය යුතුය. වීදුරු කිහිපයක් එකට අතිච්ඡාදනය වන වඩාත් සංකීර්ණ අවස්ථාවන්හිදී, අතිච්ඡාදනය වන කලාපයේ ඵලදායී පරාවර්තක දර්ශකය එක් එක් ඒවායේ පරාවර්තක දර්ශකවල ගුණිතයට සමාන වේ." + }, + "cauchyCoeff": "Cauchy සංගුණකය" + }, + "SphericalLens": { + "defBy": { + "focalDistances": "නාභීය දුර" + } + }, + "Aperature": { + "diameter": "විෂ්කම්භය" + }, + "DiffractionGrating": { + "lineDensity": "රේඛා/{{lengthUnit}}", + "slitRatio": "ස්ලිට් පළල / රේඛා පරතරය" + }, + "Ruler": { + "scaleInterval": "පරිමාණ පරතරය" + }, + "TextLabel": { + "textHere": "මෙතනින් ලියන්න", + "fontSize": "අකුරු ප්‍රමාණය", + "font": "අකුරු", + "fontStyle": "Style", + "fontStyles": { + "normal": "සාමාන්‍ය අකුරු", + "bold": "තද අකුරු", + "italic": "ඇල අකුරු", + "boldItalic": "තද ඇල අකුරු", + "oblique": "ආනත අකුරු", + "boldOblique": "තද ආනත අකුරු" + }, + "alignment": "පෙළගැස්ම", + "alignments": { + "left": "වම", + "center": "මධ්‍ය", + "right": "දකුණ" + }, + "smallCaps": "Small Caps", + "angle": "කෝණය" + }, + "LineArrow": { + "arrow": "ඉදිරියට ඊතලය", + "backArrow": "පසුපසට ඊතලය" + }, + "Drawing": { + "finishDrawing": "ඇඳීම අවසන් කරන්න" + }, + "ModuleObj": { + "module": "මොඩියුල" + }, + "CropBox": { + "title": "Export", + "cropBoxSize": "කොටුව crop කරන්න", + "format": "ආකෘතිය", + "width": "පළල", + "rayCountLimit": "කිරණ ගණන සීමාව" + } + }, + "saveModal": { + "title": "Save", + "fileName": "නම", + "rename": "Rename" + }, + "moduleModal": { + "title": "Import Modules" + }, + "languageModal": { + "title": "භාෂාව", + "translatedFraction": "පරිවර්තිතයි", + "helpTranslate": "මෙම යෙදුම පරිවර්තනය කිරීමට අපට උදවු කරන්න" + }, + "generalWarnings": { + "identicalObjects": "දර්ශනයේ සම්පූර්ණයෙන්ම අතිච්ඡාදනය වන සමාන දෘශ්‍ය මූලද්‍රව්‍ය දෙකක් ඇත." + }, + "statusBox": { + "rayCount": "කිරණ කොටස් සංඛ්‍යාව", + "totalTruncation": "කපා දැමූ දීප්තිය", + "timeElapsed": "ගතවූ කාලය", + "forceStopped": "බලහත්කාරයෙන් නතර විය.", + "mouseCoordinates": "Mouse ඛණ්ඩාංක" + }, + "footer": { + "processing": "සකසමින්... නතර කිරීමට මෙතන click කරන්න." + } +} \ No newline at end of file diff --git a/locales/sync.js b/locales/sync.js deleted file mode 100644 index c1e45240..00000000 --- a/locales/sync.js +++ /dev/null @@ -1,27 +0,0 @@ -// Run this script with node.js whenever some new items are added into en.js - -locale_name = ['en', 'zh-TW', 'zh-CN', 'ru', 'nl', 'fr', 'de', 'pl', 'ja', 'si', 'ko', 'es', 'pt-BR', 'LOCALE_ID']; -locale_files = ['en.js', 'zh_TW.js', 'zh_CN.js', 'ru.js', 'nl.js', 'fr.js', 'de.js', 'pl.js', 'ja.js', 'si.js', 'ko.js', 'es.js', 'pt_BR.js', 'template.js']; -fs = require('fs'); - -var locales = {}; -for (var i in locale_name) { - eval(fs.readFileSync(locale_files[i]).toString()); -} - -var locales_new = {}; - -for (var i in locale_name) { - var locale = {}; - for (var key in locales['en']) { - if (locales[locale_name[i]][key]) { - locale[key] = locales[locale_name[i]][key]; - } else { - locale[key] = { incomplete: true, message: locales['en'][key].message }; - } - } - fs.writeFileSync(locale_files[i], - "if (typeof locales == 'undefined') locales = {};\n" + - "locales[\"" + locale_name[i] + "\"] = " + - JSON.stringify(locale, null, 2)); -} diff --git a/locales/template.json b/locales/template.json deleted file mode 100644 index 378c0117..00000000 --- a/locales/template.json +++ /dev/null @@ -1,1149 +0,0 @@ -{ - "appName": { - "incomplete": true, - "message": "Simulator - Ray Optics Simulation" - }, - "appShortName": { - "incomplete": true, - "message": "Ray Optics" - }, - "appDesc": { - "incomplete": true, - "message": "A free, open-source web app for creating and simulating 2D geometric optical scenes." - }, - "homepage_desc": { - "incomplete": true, - "message": "Create & simulate 2D geometric optical scenes interactively.
Totally free and web-based. Source code is available on GitHub." - }, - "launch_simulator": { - "incomplete": true, - "message": "Launch Simulator" - }, - "home": { - "incomplete": true, - "message": "Home" - }, - "home_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/" - }, - "gallery": { - "incomplete": true, - "message": "Gallery" - }, - "gallery_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/gallery/" - }, - "welcome": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
To add an optical component, select a tool and click the blank space.
To load an example, please go to the Gallery page." - }, - "loading_msg": { - "incomplete": true, - "message": "Welcome to Ray Optics Simulation
Loading scene from URL... Please wait." - }, - "toolbar_title": { - "incomplete": true, - "message": "Tool: " - }, - "toolname_SingleRay": { - "incomplete": true, - "message": "Single ray" - }, - "toolname_AngleSource": { - "incomplete": true, - "message": "Point source" - }, - "toolname_PointSource": { - "incomplete": true, - "message": "Point source" - }, - "toolname_Beam": { - "incomplete": true, - "message": "Beam" - }, - "toolname_mirror_": { - "incomplete": true, - "message": "Mirror" - }, - "toolname_Mirror": { - "incomplete": true, - "message": "Mirror" - }, - "toolname_ArcMirror": { - "incomplete": true, - "message": "Mirror" - }, - "toolname_ParabolicMirror": { - "incomplete": true, - "message": "Mirror" - }, - "toolname_CustomMirror": { - "incomplete": true, - "message": "Mirror" - }, - "toolname_IdealMirror": { - "incomplete": true, - "message": "Ideal curved mirror" - }, - "toolname_glass_": { - "incomplete": true, - "message": "Glass" - }, - "toolname_blocker_": { - "incomplete": true, - "message": "Blocker" - }, - "toolname_BeamSplitter": { - "incomplete": true, - "message": "Beam Splitter" - }, - "toolname_PlaneGlass": { - "incomplete": true, - "message": "Glass" - }, - "toolname_CircleGlass": { - "incomplete": true, - "message": "Glass" - }, - "toolname_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_Glass": { - "incomplete": true, - "message": "Glass" - }, - "toolname_GrinGlass": { - "incomplete": true, - "message": "Gradient-index glass" - }, - "toolname_IdealLens": { - "incomplete": true, - "message": "Ideal lens" - }, - "toolname_SphericalLens": { - "incomplete": true, - "message": "Spherical lens" - }, - "toolname_CustomGlass": { - "incomplete": true, - "message": "Glass" - }, - "toolname_Blocker": { - "incomplete": true, - "message": "Line Blocker" - }, - "toolname_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "toolname_CircleBlocker": { - "incomplete": true, - "message": "Circle Blocker" - }, - "toolname_DiffractionGrating": { - "incomplete": true, - "message": "Diffraction GratingBeta" - }, - "toolname_Ruler": { - "incomplete": true, - "message": "Ruler" - }, - "toolname_Protractor": { - "incomplete": true, - "message": "Protractor" - }, - "tool_Detector": { - "incomplete": true, - "message": "Detector" - }, - "toolname_Detector": { - "incomplete": true, - "message": "Detector" - }, - "toolname_TextLabel": { - "incomplete": true, - "message": "Text" - }, - "toolname_LineArrow": { - "incomplete": true, - "message": "Line" - }, - "toolname_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "toolname_Handle": { - "incomplete": true, - "message": "Handle" - }, - "toolname_CropBox": { - "incomplete": true, - "message": "Export" - }, - "toolname_ModuleObj": { - "incomplete": true, - "message": "ModuleBeta" - }, - "tool_more_": { - "incomplete": true, - "message": "Other" - }, - "toolname_": { - "incomplete": true, - "message": "Move view" - }, - "modebar_title": { - "incomplete": true, - "message": "View:" - }, - "modename_light": { - "incomplete": true, - "message": "Rays" - }, - "modename_extended_light": { - "incomplete": true, - "message": "Extended rays" - }, - "modename_images": { - "incomplete": true, - "message": "All Images" - }, - "modename_observer": { - "incomplete": true, - "message": "Seen by observer" - }, - "simulateColors": { - "incomplete": true, - "message": "Simulate Colors" - }, - "File: ": { - "incomplete": true, - "message": "File" - }, - "Tools: ": { - "incomplete": true, - "message": "Tools" - }, - "tool_SingleRay": { - "incomplete": true, - "message": "Single ray" - }, - "tool_Beam": { - "incomplete": true, - "message": "Beam" - }, - "tool_PointSource": { - "incomplete": true, - "message": "Point source (360°)" - }, - "tool_AngleSource": { - "incomplete": true, - "message": "Point source (<360°)" - }, - "tool_PointSource_": { - "incomplete": true, - "message": "Point source" - }, - "tool_lightSource_": { - "incomplete": true, - "message": "Light Source" - }, - "tool_mirror_": { - "incomplete": true, - "message": "Mirror" - }, - "tool_Mirror": { - "incomplete": true, - "message": "Segment" - }, - "tool_ArcMirror": { - "incomplete": true, - "message": "Circular Arc" - }, - "tool_ParabolicMirror": { - "incomplete": true, - "message": "Parabolic" - }, - "tool_CustomMirror": { - "incomplete": true, - "message": "Custom Equation" - }, - "tool_BeamSplitter": { - "incomplete": true, - "message": "Beam Splitter" - }, - "tool_IdealMirror": { - "incomplete": true, - "message": "Ideal curved mirror" - }, - "tool_glass_": { - "incomplete": true, - "message": "Glass" - }, - "tool_blocker_": { - "incomplete": true, - "message": "Blocker" - }, - "tool_PlaneGlass": { - "incomplete": true, - "message": "Half-plane" - }, - "tool_CircleGlass": { - "incomplete": true, - "message": "Circle" - }, - "tool_CircleGrinGlass": { - "incomplete": true, - "message": "Gradient-index circle" - }, - "tool_Glass": { - "incomplete": true, - "message": "Polygon / Circular Arcs" - }, - "tool_GrinGlass": { - "incomplete": true, - "message": "Gradient-index polygon" - }, - "tool_IdealLens": { - "incomplete": true, - "message": "Ideal Lens" - }, - "tool_SphericalLens": { - "incomplete": true, - "message": "Spherical Lens" - }, - "tool_CustomGlass": { - "incomplete": true, - "message": "Custom Equation" - }, - "tool_Blocker": { - "incomplete": true, - "message": "Line Blocker" - }, - "tool_Aperture": { - "incomplete": true, - "message": "Aperture" - }, - "tool_CircleBlocker": { - "incomplete": true, - "message": "Circle Blocker" - }, - "tool_DiffractionGrating": { - "message": "Diffraction GratingBeta" - }, - "tool_Ruler": { - "incomplete": true, - "message": "Ruler" - }, - "tool_Protractor": { - "incomplete": true, - "message": "Protractor" - }, - "tool_TextLabel": { - "incomplete": true, - "message": "Text" - }, - "tool_LineArrow": { - "incomplete": true, - "message": "Line / Arrow" - }, - "tool_Drawing": { - "incomplete": true, - "message": "Drawing" - }, - "tool_": { - "incomplete": true, - "message": "Move view" - }, - "View: ": { - "incomplete": true, - "message": "View" - }, - "Settings: ": { - "incomplete": true, - "message": "Settings" - }, - "moresettings": { - "incomplete": true, - "message": "More" - }, - "mode_rays": { - "incomplete": true, - "message": "Rays" - }, - "mode_extended": { - "incomplete": true, - "message": "Extended rays" - }, - "mode_images": { - "incomplete": true, - "message": "All Images" - }, - "mode_observer": { - "incomplete": true, - "message": "Seen by Observer" - }, - "zoom": { - "incomplete": true, - "message": "Zoom" - }, - "help": { - "incomplete": true, - "message": "Help" - }, - "rayDensity": { - "incomplete": true, - "message": "Ray Density" - }, - "raydensity": { - "incomplete": true, - "message": "Ray Density:" - }, - "undo": { - "incomplete": true, - "message": "Undo" - }, - "redo": { - "incomplete": true, - "message": "Redo" - }, - "reset": { - "incomplete": true, - "message": "Reset" - }, - "save": { - "incomplete": true, - "message": "Save" - }, - "rename": { - "incomplete": true, - "message": "Rename" - }, - "get_link": { - "incomplete": true, - "message": "Copy Shareable Link" - }, - "export_svg": { - "incomplete": true, - "message": "Export as PNG/SVG" - }, - "view_gallery": { - "incomplete": true, - "message": "View Gallery" - }, - "save_name": { - "incomplete": true, - "message": "Name" - }, - "save_cancel": { - "incomplete": true, - "message": "Cancel" - }, - "save_description": { - "incomplete": true, - "message": "
  • You may use Settings -> Auto sync URL instead of saving to a file.
  • Click \"Rename\" to change the title without saving to a file.
  • You may consider contribute a new item to the Gallery.
" - }, - "open": { - "incomplete": true, - "message": "Open" - }, - "layoutaids": { - "incomplete": true, - "message": "Layout Aids" - }, - "lockObjs": { - "incomplete": true, - "message": "Lock Objects" - }, - "showGrid": { - "incomplete": true, - "message": "Grid" - }, - "snapToGrid": { - "incomplete": true, - "message": "Snap to Grid" - }, - "snaptogrid": { - "incomplete": true, - "message": "Snap to Grid" - }, - "length_unit_popover": { - "incomplete": true, - "message": "The unit of length used in this simulator (except for wavelengths) is an arbitrary unit, which can be interpreted as any physical unit (e.g. millimeters) as long as it is consistent throughout the simulation. If the unit appears too small or too large, please adjust Settings -> Length Scale." - }, - "lengthScale": { - "incomplete": true, - "message": "Length ScaleBeta" - }, - "lengthScale_popover": { - "incomplete": true, - "message": "If the default unit of length is too small or too large to model a physical system when interpreted as a common physical unit (e.g. millimeters), this factor can be used to scale the appearance (e.g. line widths) in the scene." - }, - "brightness": { - "incomplete": true, - "message": "Brightness" - }, - "wavelength": { - "incomplete": true, - "message": "Wavelength (nm)" - }, - "dichroic": { - "incomplete": true, - "message": "Dichroic" - }, - "filter": { - "incomplete": true, - "message": "Filter" - }, - "bandwidth": { - "incomplete": true, - "message": "Bandwidth (nm)" - }, - "invert": { - "incomplete": true, - "message": "Invert" - }, - "emisAngle": { - "incomplete": true, - "message": "Emission Angle (°)" - }, - "mirrored": { - "incomplete": true, - "message": "Mirrored" - }, - "lineDensity": { - "incomplete": true, - "message": "Lines/mm" - }, - "slitRatio": { - "incomplete": true, - "message": "Slit width / line spacing" - }, - "customBrightness": { - "incomplete": true, - "message": "Custom Brightness" - }, - "customBrightness_note_popover": { - "incomplete": true, - "message": "When on, the brightnesses of the diffracted rays are customized by an array of numbers corresponding to m = 0, 1, -1, 2, -2, .... The number is to be normalized to the brightness of the incident ray. The values not in the array are set to 0. For example, \"1, 0.5, 0.5\" means the m=0 ray has the same brightness as the incident ray, the m=1 and m=-1 rays have half the brightness, and all other rays are ignored." - }, - "symmetric": { - "incomplete": true, - "message": "Symmetric" - }, - "eqn_note": { - "incomplete": true, - "message": "
  • Supported constants:
    pi e
  • Supported operators:
    + - * / ^
  • Supported functions:
    sqrt sin cos tan sec csc cot sinh cosh tanh log exp arcsin arccos arctan arcsinh arccosh arctanh floor round ceil trunc sgn max min abs
" - }, - "symbolic_grin": { - "incomplete": true, - "message": "Symbolic body-merging" - }, - "grin_refractive_index": { - "incomplete": true, - "message": "
  • Supported constants:
    pi e
  • Supported operators:
    + - * / ^
  • Supported functions:
    sqrt sin cos tan sec csc cot sinh cosh tanh log arcsin arccos arctan
  • To simulate chromatic dispersion, use parameter lambda for the vacuum wavelength in nanometers.Beta
  • Only supports differentiable functions.
  • The origin of n(x,y) is in the absolute coordinates and does not move with the object. You may double-click a control-point to inspect its absolute coordinates.
  • For a more accurate simulation, see \"More options...\"
" - }, - "symbolic_grin_note_popover": { - "incomplete": true, - "message": "

This toggle applies to all GRIN objects in the simulation.

This simulator has currently two implementations of light propagation between different mediums, for GRIN objects - numerical and symbolic (see 'multRefIndex' and 'devRefIndex' functions in 'CircleGrinGlass.js').

The numerical implementation is faster but doesn't always work properly (depending on the specific case) in scenarios when used with more than one GRIN object, such that at least one of them has a refractive index function which is not defined in the entire plane, while the symbolic implementation is slower but robust to such problems.

" - }, - "focalLength": { - "incomplete": true, - "message": "Focal length" - }, - "cartesianSign": { - "incomplete": true, - "message": "Cartesian Sign Convention" - }, - "refIndex": { - "incomplete": true, - "message": "Refractive index*" - }, - "radii_of_curvature": { - "incomplete": true, - "message": "Radii of Curvature" - }, - "focal_distances": { - "incomplete": true, - "message": "Focal Distances" - }, - "refIndex_origin": { - "incomplete": true, - "message": "Origin of n(x,y)" - }, - "stepSize": { - "incomplete": true, - "message": "Numerical solver step size" - }, - "intersectTol": { - "incomplete": true, - "message": "Intersection tolerance" - }, - "random": { - "incomplete": true, - "message": "Random" - }, - "lambert": { - "incomplete": true, - "message": "Lambertian" - }, - "diameter": { - "incomplete": true, - "message": "Diameter" - }, - "irradMap": { - "incomplete": true, - "message": "Irradiance Map" - }, - "binSize": { - "incomplete": true, - "message": "Bin Size" - }, - "scaleInterval": { - "incomplete": true, - "message": "Scale interval" - }, - "exportData": { - "incomplete": true, - "message": "Export data" - }, - "demodulize": { - "incomplete": true, - "message": "Demodulize" - }, - "fontSize": { - "incomplete": true, - "message": "Font Size" - }, - "font": { - "incomplete": true, - "message": "Font" - }, - "fontStyle": { - "incomplete": true, - "message": "Style" - }, - "normal": { - "incomplete": true, - "message": "Normal" - }, - "bold": { - "incomplete": true, - "message": "Bold" - }, - "italic": { - "incomplete": true, - "message": "Italic" - }, - "bolditalic": { - "incomplete": true, - "message": "Bold Italic" - }, - "oblique": { - "incomplete": true, - "message": "Oblique" - }, - "boldoblique": { - "incomplete": true, - "message": "Bold Oblique" - }, - "alignment": { - "incomplete": true, - "message": "Alignment" - }, - "left": { - "incomplete": true, - "message": "Left" - }, - "center": { - "incomplete": true, - "message": "Centre" - }, - "right": { - "incomplete": true, - "message": "Right" - }, - "text_here": { - "incomplete": true, - "message": "Text Here" - }, - "smallCaps": { - "incomplete": true, - "message": "Small Caps" - }, - "angle": { - "incomplete": true, - "message": "Angle (°)" - }, - "arrow": { - "incomplete": true, - "message": "Forward arrow" - }, - "backArrow": { - "incomplete": true, - "message": "Backward arrow" - }, - "stop_drawing": { - "incomplete": true, - "message": "Finish Drawing" - }, - "cropBoxSize": { - "incomplete": true, - "message": "Crop Box Size" - }, - "format": { - "incomplete": true, - "message": "Format" - }, - "width": { - "incomplete": true, - "message": "Width" - }, - "rayCountLimit": { - "incomplete": true, - "message": "Ray count limit" - }, - "transformation": { - "incomplete": true, - "message": "TransformationBeta" - }, - "default": { - "incomplete": true, - "message": "Default" - }, - "translation": { - "incomplete": true, - "message": "Translation" - }, - "xTranslation": { - "incomplete": true, - "message": "X Translation" - }, - "yTranslation": { - "incomplete": true, - "message": "Y Translation" - }, - "rotation": { - "incomplete": true, - "message": "Rotation" - }, - "scaling": { - "incomplete": true, - "message": "Scaling" - }, - "beam_warning": { - "incomplete": true, - "message": "Image detection may not work with divergent/random beams." - }, - "image_detection_warning": { - "incomplete": true, - "message": "This tool does not support image detection." - }, - "non_simulateColors_warning": { - "incomplete": true, - "message": "This tool only works when \"Simulate Color\" is on." - }, - "brightness_note_popover": { - "incomplete": true, - "message": "

Only effective if 'Ray Density' is high enough.

To control the numbers of rays emitted, please adjust the global 'Ray Density' slider instead.

" - }, - "refIndex_note_popover": { - "incomplete": true, - "message": "

*Relative if inside another glass

If this object is to be simulated with (absolute) refractive index n₁, but is placed inside another glass with refractive index n₀, then you should set the refractive index to n₁/n₀ here. In more complicated cases that several glasses overlap together, the effective reflective index of the overlapping region equals the product of the reflective indices of individual ones.

" - }, - "stepSize_note_popover": { - "incomplete": true, - "message": "

Step size of Euler's method for solving the eikonal ray equation - see 'step' function and documentation inside the 'CircleGrinGlass.js' file, for more information.

" - }, - "eps_CircleGrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length]^2.

This numerical tolerance is used in the functions 'isOutsideGlass', 'isInsideGlass' and 'isOnBoundary', inside the 'CircleGrinGlass.js' file.

" - }, - "eps_GrinGlass_note_popover": { - "incomplete": true, - "message": "

Units - [length].

This numerical tolerance is used in the functions 'isOnBoundary' and 'countIntersections', inside the 'GrinGlass.js' file.

" - }, - "cauchyCoeff": { - "incomplete": true, - "message": "Cauchy coefficient" - }, - "transRatio": { - "incomplete": true, - "message": "Transmission Ratio" - }, - "applytoall": { - "incomplete": true, - "message": "Apply to All" - }, - "duplicate": { - "incomplete": true, - "message": "Duplicate" - }, - "delete": { - "incomplete": true, - "message": "Delete" - }, - "unselect": { - "incomplete": true, - "message": "Unselect" - }, - "unselect_popover": { - "incomplete": true, - "message": "Unselect this object (Right-click on blank space has the same function.)" - }, - "showadvanced": { - "incomplete": true, - "message": "More options..." - }, - "processing": { - "incomplete": true, - "message": "Processing... Click here to stop." - }, - "contribute": { - "incomplete": true, - "message": "Contribute" - }, - "github": { - "incomplete": true, - "message": "GitHub" - }, - "about": { - "incomplete": true, - "message": "About" - }, - "about_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/about" - }, - "translate": { - "incomplete": true, - "message": "Help us translate this app" - }, - "translated": { - "incomplete": true, - "message": "translated" - }, - "undo_popover": { - "incomplete": true, - "message": "Undo last action. (Ctrl+Z)" - }, - "redo_popover": { - "incomplete": true, - "message": "Redo last action. (Ctrl+Y)" - }, - "reset_popover": { - "incomplete": true, - "message": "Reset all changes." - }, - "save_popover": { - "incomplete": true, - "message": "Save the current scene as a file." - }, - "open_popover": { - "incomplete": true, - "message": "Open an existing file or background image. The background image will be shown from the coordinate origin. (Or drop the file)" - }, - "get_link_popover": { - "incomplete": true, - "message": "Copy and go to the direct URL for the current scene, which can be used for sharing (possibly via a URL shortener). Also see Settings -> Auto sync URL." - }, - "get_link_warning": { - "incomplete": true, - "message": "The URL is too long that it may not work on some platforms. You may need to use \"Save\" and share the file instead." - }, - "export_svg_warning": { - "incomplete": true, - "message": "Export to SVG: Color mixtures and relative refractive indices below 1 are not supported." - }, - "export_ray_count_warning": { - "incomplete": true, - "message": "The current number of rays in the scene is larger than the ray count limit. You may need to increase the ray count limit in the Crop Box options." - }, - "view_gallery_popover": { - "incomplete": true, - "message": "Go to the Gallery webpage to load an example." - }, - "tool_SingleRay_popover": { - "incomplete": true, - "message": "A single ray of light defined by two points. (Drag or Click to create. The first point is the source, shooting toward the second point.)" - }, - "tool_Beam_popover": { - "incomplete": true, - "message": "A parallel or divergent beam of rays emerges from a line segment, with density controlled by the 'Ray density' slider. (Drag or click to create.)" - }, - "tool_PointSource_popover": { - "incomplete": true, - "message": "Rays emerge from a single point, with number controlled by the 'Ray density' slider. (Click to create.)" - }, - "tool_AngleSource_popover": { - "incomplete": true, - "message": "Point source with a given emission angle." - }, - "tool_Mirror_popover": { - "incomplete": true, - "message": "Simulate the reflection of light on a mirror. (Drag or click to create.)" - }, - "tool_ArcMirror_popover": { - "incomplete": true, - "message": "A mirror whose shape is part of a circle, which is defined by three points. (Drag or click to create. The first 2 points define the gap between arc's edges, the last point defines the arc's size.)" - }, - "tool_ParabolicMirror_popover": { - "incomplete": true, - "message": "A mirror whose shape is a parabola, which is defined by three points. (Drag or click to create.)" - }, - "tool_CustomMirror_popover": { - "incomplete": true, - "message": "A mirror whose shape is defined by a custom equation y = f(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0). (Drag or click to create.)" - }, - "tool_BeamSplitter_popover": { - "incomplete": true, - "message": "A mirror that transmits a percentage of incoming light. (Drag or click to create.)" - }, - "tool_IdealMirror_popover": { - "incomplete": true, - "message": "The idealized 'curved' mirror which obeys exactly the mirror equation (1/p + 1/q = 1/f). The focal length can be set directly. (Drag or click to create.)" - }, - "tool_PlaneGlass_popover": { - "incomplete": true, - "message": "Simulate the refraction and reflection of light on a surface. (Drag or click to create.)" - }, - "tool_CircleGlass_popover": { - "incomplete": true, - "message": "Glass with a circle shape, defined by its center and a point on the surface. (Drag or click to create.)" - }, - "tool_CircleGrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a circular boundary. (Drag or click to create.)" - }, - "tool_Glass_popover": { - "incomplete": true, - "message": "Glass with any shapes constructed from line segments and circular arcs. (Click to create a segment, drag to create an arc, click on the starting point when finish drawing.)" - }, - "tool_GrinGlass_popover": { - "incomplete": true, - "message": "Glass with a custom refractive index function n(x,y) and a polygonal boundary. WARNING: Only simple polygons are supported, otherwise the behavior is unpredictable. (Click to create a segment, click on the starting point when finish drawing.)" - }, - "tool_IdealLens_popover": { - "incomplete": true, - "message": "An ideal lens which obeys exactly the thin lens equation (1/p + 1/q = 1/f). The focal length can be set directly. (Drag or click to create.)" - }, - "tool_SphericalLens_popover": { - "incomplete": true, - "message": "A spherical lens. (Click to create.)" - }, - "tool_CustomGlass_popover": { - "incomplete": true, - "message": "Glass with the shape defined by a custom inequality f(x) < y < g(x), where (x,y) is in the transformed coordinates in which the two control points are (-1,0) and (1,0). (Drag or click to create.)" - }, - "tool_Blocker_popover": { - "incomplete": true, - "message": "A line-segment light blocker which absorbs the incident rays. (Drag or click to create.)" - }, - "tool_Aperture_popover": { - "incomplete": true, - "message": "A pair of light blockers which absorbs the incident rays. The size of the hole can be adjusted symmetrically. (Drag or click the two endpoints to create.)" - }, - "tool_CircleBlocker_popover": { - "incomplete": true, - "message": "A circle light blocker which absorbs the incident rays. (Drag or click to create.)" - }, - "tool_DiffractionGrating_popover": { - "incomplete": true, - "message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)" - }, - "tool_Ruler_popover": { - "incomplete": true, - "message": "A ruler from a point for zero and another point. (Drag or click to create.)" - }, - "tool_Protractor_popover": { - "incomplete": true, - "message": "A protractor defined from the center and another point for the zero direction. The scale is in degrees. (Drag or click to create.)" - }, - "tool_Detector_popover": { - "incomplete": true, - "message": "A tool for measuring the rate of energy flow (P), the rate of perpendicular momentum flow (F⊥), and the rate of parallel momentum flow (F∥) through a line segment. (Drag or click to create the line segment.) The units are arbitrary." - }, - "tool_Detector_info_popover": { - "incomplete": true, - "message": "
  • P: The rate of energy flow (flux) in B/s (see below).
  • F⊥: The rate of perpendicular momentum flow in (B/s)/c.
  • F∥: The rate of parallel momentum flow in (B/s)/c.
  • The irradiance in the exported CSV is in (B/s)/L.
  • L is the arbitrary unit of length used in this simulator.
  • B is an arbitrary unit of radiant flux or luminous flux, corresponding to the unit of the \"Brightness\" option being B/L for non-Lambertian beams and 500B/360° for point sources.
  • The dimensionless factor s is the \"Brightness Scale\" shown in Settings -> Show status box, which equals 1 when \"Ray Density\" is above some threshold and proportional to \"Ray Density\" otherwise.
  • If some rays are truncated in the infinite series of internal reflection, the total truncation is shown as error estimates.
" - }, - "tool_TextLabel_popover": { - "incomplete": true, - "message": "A text label." - }, - "tool_LineArrow_popover": { - "incomplete": true, - "message": "A line segment or arrow. (Drag or click to create.)" - }, - "tool_Drawing_popover": { - "incomplete": true, - "message": "A freehand drawing tool. (Drag to draw.)" - }, - "tool__popover": { - "incomplete": true, - "message": "Drag to move the view. (Mouse right button drag has the same function.)" - }, - "mode_rays_popover": { - "incomplete": true, - "message": "Show the rays. When the 'Ray density' is high, they appear to be continuous." - }, - "mode_extended_popover": { - "incomplete": true, - "message": "Show both the rays and its extension. Orange indicates backward extensions, and gray indicates forward ones.
When 'Simulate Colors' is on, they are shown in source colors and distinguished by dashing instead." - }, - "mode_images_popover": { - "incomplete": true, - "message": "Show the position of all images. Yellow points indicate real images, orange indicates virtual images, and gray (none in this picture) indicates virtual objects. Note that some images cannot be detected if 'Ray density' is not high enough.
When 'Simulate Colors' is on, they are shown in source colors and distinguished by dot sizes instead." - }, - "mode_observer_popover": { - "incomplete": true, - "message": "Simulate the rays and images seen from some position. The blue circle is the observer. Any rays crossing it are considered to be 'observed'. The observer does not know where the rays actually begin, but may think they begin at some point(s) if they intersect there. The rays are shown in blue, and the points in yellow (real) or orange (virtual). (Drag the big blue dot to move the observer.)
When 'Simulate Colors' is on, they are shown in source colors instead." - }, - "simulateColors_popover": { - "incomplete": true, - "message": "Simulate colors (wavelengths) of light sources, mixture of colors, color filtering of blockers and mirrors, and chromatic dispersion of glasses. You can set those parameters for those objects when selected. To simulate color spectra, overlap rays with different wavelengths. The colors shown on the screen are only rough approximations, and can be very inaccurate when 'Ray density' is too high or too low." - }, - "rayDensity_popover": { - "incomplete": true, - "message": "Determines the number of rays to be emitted by beams and point sources. This also affects the accuracy of image detection and color rendering." - }, - "showGrid_popover": { - "incomplete": true, - "message": "Defines the visibility of the background grid." - }, - "grid_popover": { - "incomplete": true, - "message": "Defines whether to snap to grid." - }, - "lockObjs_popover": { - "incomplete": true, - "message": "Defines whether the objects can be moved or not." - }, - "zoom_popover": { - "incomplete": true, - "message": "Zoom the view with percentage." - }, - "help_popover": { - "incomplete": true, - "message": "Constrained dragging

When dragging an object, hold Shift to limit to horizontal/vertical; hold Ctrl to clone. When creating a line-shaped object or dragging its endpoints, hold Shift to lock the angle or snap to 0°, 45°, 90°; hold Ctrl to rotate/scale about its center.

Group, rotate, and scale objects

Hold Ctrl, click several control points (e.g. endpoints), then click empty space to group these points and create a handle. Drag the handle (or press arrow keys) to move the group; Shift+drag to limit to horizontal/vertical; Ctrl+drag to rotate, Ctrl+Shift+drag to scale. Drag the \"+\" to set rotation/scaling center. Click the handle and press Ctrl+D to duplicate the group; press Delete to ungroup.

Edit coordinates directly

Double-click or right-click the control point (e.g. endpoint) of the object, edit the (x,y) coordinates, then press Enter.

Keyboard shortcuts

When an object is selected (by clicking it), press arrow keys to move; Ctrl+D to duplicate; Delete key to delete.

Contact Us

The suggested way is to go to Discussions or Issues on GitHub. If you do not use GitHub, you can also email us at ray-optics@phydemo.app.

Direct contributions are also welcome (see the contribution guide).

" - }, - "show_help_popups": { - "incomplete": true, - "message": "Show help popups" - }, - "show_help_popups_popover": { - "incomplete": true, - "message": "Defines whether to show help popups when hovering over buttons. (Reload the page to take effect.)" - }, - "show_json_editor": { - "incomplete": true, - "message": "Show JSON editorBeta" - }, - "show_json_editor_popover": { - "incomplete": true, - "message": "Show the code editor for the JSON representation of the scene, which is needed when creating a custom module (See Tools -> Other -> Import Modules -> Make custom modules)." - }, - "show_status": { - "incomplete": true, - "message": "Show status box" - }, - "show_status_popover": { - "incomplete": true, - "message": "Show the status box, which includes the mouse coordinates, performance information, and the truncated brightness (the total brightness of the rays truncated in the infinite series of internal reflection)." - }, - "auto_sync_url": { - "incomplete": true, - "message": "Auto sync URL" - }, - "auto_sync_url_popover": { - "incomplete": true, - "message": "When enabled, the URL will be updated automatically with the current scene, so you don't need to keep saving the scene manually. To set the title, use File -> Save -> Rename." - }, - "auto_sync_url_warning": { - "incomplete": true, - "message": "The scene is too large to sync with URL. Please save it manually." - }, - "gridSize": { - "incomplete": true, - "message": "Grid Size" - }, - "observer_size": { - "incomplete": true, - "message": "Observer Size" - }, - "language": { - "incomplete": true, - "message": "Language" - }, - "close": { - "incomplete": true, - "message": "Close" - }, - "advanced_help": { - "incomplete": true, - "message": "For advanced help, see the help icon in the lower-right corner." - }, - "ray_count": { - "incomplete": true, - "message": "Number of ray segments: " - }, - "total_truncation": { - "incomplete": true, - "message": "Truncated brightness: " - }, - "brightness_scale": { - "incomplete": true, - "message": "Brightness Scale: " - }, - "time_elapsed": { - "incomplete": true, - "message": "Time elapsed (ms): " - }, - "force_stopped": { - "incomplete": true, - "message": "Force stopped." - }, - "mouse_coordinates": { - "incomplete": true, - "message": "Mouse coordinates: " - }, - "modules_tutorial": { - "incomplete": true, - "message": "Make custom modules" - }, - "modules_tutorial_url": { - "incomplete": true, - "message": "https://phydemo.app/ray-optics/modules/tutorial" - }, - "identical_optical_objects_warning": { - "incomplete": true, - "message": "There are two identical optical elements in the scene that overlap completely. This may cause unexpected behavior." - }, - "import_modules": { - "incomplete": true, - "message": "Import Modules..." - }, - "import_modules_title": { - "incomplete": true, - "message": "Import Modules" - }, - "modules_url": { - "incomplete": true, - "message": "../modules/modules.html" - }, - "remove_module": { - "incomplete": true, - "message": "Remove module" - }, - "module_conflict": { - "incomplete": true, - "message": "A different module with the same name already exists in the current scene. You may enter a new name, or leave it the same to overwrite the existing module." - }, - "brightness_inconsistent_warning": { - "incomplete": true, - "message": "The brightnesses of two or more light sources saturate with inconsistent ratios. This may lead to wrong detector readings and color rendering. Please increase the ray density or reduce the brightnesses of the light sources." - } -} \ No newline at end of file diff --git a/locales/zh-CN.json b/locales/zh-CN.json deleted file mode 100644 index 2631e0c7..00000000 --- a/locales/zh-CN.json +++ /dev/null @@ -1,863 +0,0 @@ -{ - "appName": { - "message": "模拟器 - 射线光学模拟" - }, - "appShortName": { - "message": "射线光学" - }, - "appDesc": { - "message": "自由、开源的网页程序,用于建立及模拟二维几何光学场景。" - }, - "homepage_desc": { - "message": "建立二维几何光学场景,并实时模拟光线行为。
完全免费,免下载,源代码公开于 GitHub。" - }, - "launch_simulator": { - "message": "启动程序" - }, - "home": { - "message": "首页" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/cn/" - }, - "gallery": { - "message": "作品集" - }, - "gallery_url": { - "message": "https://phydemo.app/ray-optics/cn/gallery/" - }, - "welcome": { - "message": "欢迎使用“射线光学模拟”
若要加入光学元件,请选择工具并点击空白处。
若要载入示例,请前往“作品集”页面。" - }, - "loading_msg": { - "message": "欢迎使用“射线光学模拟”
正在从网址载入场景... 请稍候。" - }, - "toolbar_title": { - "message": "工具:" - }, - "toolname_SingleRay": { - "message": "单一光线" - }, - "toolname_AngleSource": { - "message": "点光源" - }, - "toolname_PointSource": { - "message": "点光源" - }, - "toolname_Beam": { - "message": "光束" - }, - "toolname_mirror_": { - "message": "镜子" - }, - "toolname_Mirror": { - "message": "镜子" - }, - "toolname_ArcMirror": { - "message": "镜子" - }, - "toolname_ParabolicMirror": { - "message": "镜子" - }, - "toolname_CustomMirror": { - "message": "镜子" - }, - "toolname_IdealMirror": { - "message": "理想曲面镜" - }, - "toolname_glass_": { - "message": "透光物" - }, - "toolname_blocker_": { - "message": "遮光物" - }, - "toolname_BeamSplitter": { - "message": "分光镜" - }, - "toolname_PlaneGlass": { - "message": "透光物" - }, - "toolname_CircleGlass": { - "message": "透光物" - }, - "toolname_CircleGrinGlass": { - "message": "渐变折射率透光物" - }, - "toolname_Glass": { - "message": "透光物" - }, - "toolname_GrinGlass": { - "message": "渐变折射率透光物" - }, - "toolname_IdealLens": { - "message": "理想透镜" - }, - "toolname_SphericalLens": { - "message": "球面透镜" - }, - "toolname_CustomGlass": { - "message": "透光物" - }, - "toolname_Blocker": { - "message": "吸光片" - }, - "toolname_Aperture": { - "message": "光圈" - }, - "toolname_CircleBlocker": { - "message": "圆形遮光物" - }, - "toolname_DiffractionGrating": { - "message": "衍射光栅Beta" - }, - "toolname_Ruler": { - "message": "直尺" - }, - "toolname_Protractor": { - "message": "量角器" - }, - "tool_Detector": { - "message": "探测器" - }, - "toolname_Detector": { - "message": "探测器" - }, - "toolname_TextLabel": { - "message": "文字" - }, - "toolname_LineArrow": { - "message": "线段" - }, - "toolname_Drawing": { - "message": "绘图" - }, - "toolname_Handle": { - "message": "控制杆" - }, - "toolname_CropBox": { - "message": "导出" - }, - "toolname_ModuleObj": { - "message": "模块Beta" - }, - "tool_more_": { - "message": "其他" - }, - "toolname_": { - "message": "移动画面" - }, - "modebar_title": { - "message": "视图:" - }, - "modename_light": { - "message": "光线" - }, - "modename_extended_light": { - "message": "延长光线" - }, - "modename_images": { - "message": "所有像" - }, - "modename_observer": { - "message": "观察者所见" - }, - "simulateColors": { - "message": "模拟色彩" - }, - "File: ": { - "message": "文件" - }, - "Tools: ": { - "message": "工具" - }, - "tool_SingleRay": { - "message": "单一光线" - }, - "tool_Beam": { - "message": "光束" - }, - "tool_PointSource": { - "message": "点光源 (360°)" - }, - "tool_AngleSource": { - "message": "点光源 (<360°)" - }, - "tool_PointSource_": { - "message": "点光源" - }, - "tool_lightSource_": { - "message": "光源" - }, - "tool_mirror_": { - "message": "镜子" - }, - "tool_Mirror": { - "message": "线段" - }, - "tool_ArcMirror": { - "message": "圆弧" - }, - "tool_ParabolicMirror": { - "message": "抛物线" - }, - "tool_CustomMirror": { - "message": "自定义函数" - }, - "tool_BeamSplitter": { - "message": "分光镜" - }, - "tool_IdealMirror": { - "message": "理想曲面镜" - }, - "tool_glass_": { - "message": "透光物" - }, - "tool_blocker_": { - "message": "遮光物" - }, - "tool_PlaneGlass": { - "message": "半平面" - }, - "tool_CircleGlass": { - "message": "圆形" - }, - "tool_CircleGrinGlass": { - "message": "渐变折射率圆形" - }, - "tool_Glass": { - "message": "多边形 / 圆弧" - }, - "tool_GrinGlass": { - "message": "渐变折射率多边形" - }, - "tool_IdealLens": { - "message": "理想透镜" - }, - "tool_SphericalLens": { - "message": "球面透镜" - }, - "tool_CustomGlass": { - "message": "自定义函数" - }, - "tool_Blocker": { - "message": "吸光片" - }, - "tool_Aperture": { - "message": "光圈" - }, - "tool_CircleBlocker": { - "message": "圆形遮光物" - }, - "tool_DiffractionGrating": { - "message": "衍射光栅Beta" - }, - "tool_Ruler": { - "message": "直尺" - }, - "tool_Protractor": { - "message": "量角器" - }, - "tool_TextLabel": { - "message": "文字" - }, - "tool_LineArrow": { - "message": "线段 / 箭头" - }, - "tool_Drawing": { - "message": "绘图" - }, - "tool_": { - "message": "移动画面" - }, - "View: ": { - "message": "视图" - }, - "Settings: ": { - "message": "设定" - }, - "moresettings": { - "message": "更多选项" - }, - "mode_rays": { - "message": "光线" - }, - "mode_extended": { - "message": "延长光线" - }, - "mode_images": { - "message": "所有像" - }, - "mode_observer": { - "message": "观察者所见" - }, - "zoom": { - "message": "缩放" - }, - "help": { - "message": "帮助" - }, - "rayDensity": { - "message": "光线密度" - }, - "raydensity": { - "message": "光线密度:" - }, - "undo": { - "message": "撤销" - }, - "redo": { - "message": "重做" - }, - "reset": { - "message": "清空" - }, - "save": { - "message": "保存" - }, - "rename": { - "message": "重命名" - }, - "get_link": { - "message": "复制分享连结" - }, - "export_svg": { - "message": "导出为PNG/SVG" - }, - "view_gallery": { - "message": "浏览作品集" - }, - "save_name": { - "message": "名称" - }, - "save_cancel": { - "message": "取消" - }, - "save_description": { - "message": "
  • 您可使用设定->自动同步网址而不必存成文件。
  • 按「重命名」会改变标题但不会存成文件。
  • 您可以考虑贡献新的项目「作品集」中。
" - }, - "open": { - "message": "打开" - }, - "layoutaids": { - "message": "排版辅助" - }, - "lockObjs": { - "message": "锁定物件" - }, - "showGrid": { - "message": "网格" - }, - "snapToGrid": { - "message": "对齐网格" - }, - "snaptogrid": { - "message": "对齐网格" - }, - "length_unit_popover": { - "message": "本模拟器中的长度单位(除波长外)为一个任意单位。您可将其视为任何物理单位(例如毫米),只要在整个模拟中保持一致。如果单位看起来太小或太大,请调整设定->长度尺度。" - }, - "lengthScale": { - "message": "长度尺度Beta" - }, - "lengthScale_popover": { - "message": "如果将默认的长度单位视为常见的物理单位(例如毫米)时,模拟的物理系统看起来太小或太大,则可以使用此比例来缩放场景中的外观(例如线宽)。" - }, - "brightness": { - "message": "亮度" - }, - "wavelength": { - "message": "波长 (nm)" - }, - "dichroic": { - "message": "二色性" - }, - "filter": { - "message": "滤光" - }, - "bandwidth": { - "message": "带宽 (nm)" - }, - "invert": { - "message": "反向" - }, - "emisAngle": { - "message": "发射角 (°)" - }, - "mirrored": { - "message": "反射" - }, - "lineDensity": { - "message": "线数/mm" - }, - "slitRatio": { - "message": "狭缝宽度 / 线间距" - }, - "customBrightness": { - "message": "自定义亮度" - }, - "customBrightness_note_popover": { - "message": "启用时,衍射光的亮度将由一数值数组来决定,对应到 m = 0, 1, -1, 2, -2, ...。这些数字为相对于入射光的亮度。数组中没有的数值将被设为0。例如,\"1, 0.5, 0.5\" 表示 m=0 的光线与入射光的亮度相同,m=1 与 m=-1 的光线为入射光的一半,其他光线则被忽略。" - }, - "symmetric": { - "message": "对称" - }, - "eqn_note": { - "message": "
  • 支持的常数:
    pi e
  • 支持的运算符:
    + - * / ^
  • 支持的函数:
    sqrt sin cos tan sec csc cot sinh cosh tanh log exp arcsin arccos arctan arcsinh arccosh arctanh floor round ceil trunc sgn max min abs
" - }, - "symbolic_grin": { - "message": "符号式物体融合" - }, - "grin_refractive_index": { - "message": "
  • 支持的常数:
    pi e
  • 支持的运算符:
    + - * / ^
  • 支持的函数:
    sqrt sin cos tan sec csc cot sinh cosh tanh log arcsin arccos arctan
  • 如需模拟色散,请用参数 lambda 代表真空中波长,单位为纳米。Beta
  • 仅支持可微函数。
  • n(x,y)的原点为绝对座标,不跟随对象移动。在控制点上点两下可显示其绝对座标。
  • 如需较精确的模拟,请见「更多选项...」
" - }, - "symbolic_grin_note_popover": { - "message": "

本选项会套用至所有渐变折射率透光物。

本模拟器目前有两种光线经过不同渐变折射率介质的实作 - 数值与符号(见 'CircleGrinGlass.js' 中的 'multRefIndex' 与 'devRefIndex' 函数)。

数值的实作较快,但使用多个渐变折射率介质,且至少有一个介质的折射率没有在整个平面上有定义时,无法在所有情况下正常运作(取决于具体情况)。相较之下,符号的实作较慢但在这种情况下仍可正常运作。

" - }, - "focalLength": { - "message": "焦距" - }, - "cartesianSign": { - "message": "笛卡尔符号约定" - }, - "refIndex": { - "message": "折射率*" - }, - "radii_of_curvature": { - "message": "曲率半径" - }, - "focal_distances": { - "message": "前/后焦距" - }, - "refIndex_origin": { - "message": "n(x,y)的原点" - }, - "stepSize": { - "message": "数值求解器步长" - }, - "intersectTol": { - "message": "相交容忍度" - }, - "random": { - "message": "随机" - }, - "lambert": { - "message": "朗伯" - }, - "diameter": { - "message": "直径" - }, - "irradMap": { - "message": "辐照度图" - }, - "binSize": { - "message": "组距" - }, - "scaleInterval": { - "message": "刻度间距" - }, - "exportData": { - "message": "导出数据" - }, - "demodulize": { - "message": "取消模块化" - }, - "fontSize": { - "message": "字型大小" - }, - "font": { - "message": "字型" - }, - "fontStyle": { - "message": "样式" - }, - "normal": { - "message": "正常" - }, - "bold": { - "message": "粗体" - }, - "italic": { - "message": "斜体" - }, - "bolditalic": { - "message": "粗斜体" - }, - "oblique": { - "message": "倾斜" - }, - "boldoblique": { - "message": "粗倾斜" - }, - "alignment": { - "message": "对齐" - }, - "left": { - "message": "左" - }, - "center": { - "message": "中" - }, - "right": { - "message": "右" - }, - "text_here": { - "message": "在此输入文字" - }, - "smallCaps": { - "message": "小型大写" - }, - "angle": { - "message": "角度 (°)" - }, - "arrow": { - "message": "前向箭头" - }, - "backArrow": { - "message": "后向箭头" - }, - "stop_drawing": { - "message": "停止绘图" - }, - "cropBoxSize": { - "message": "剪取框大小" - }, - "format": { - "message": "格式" - }, - "width": { - "message": "宽度" - }, - "rayCountLimit": { - "message": "光线数量上限" - }, - "transformation": { - "message": "变换Beta" - }, - "default": { - "message": "默认" - }, - "translation": { - "message": "平移" - }, - "xTranslation": { - "message": "X 平移" - }, - "yTranslation": { - "message": "Y 平移" - }, - "rotation": { - "message": "旋转" - }, - "scaling": { - "message": "缩放" - }, - "beam_warning": { - "message": "使用发散或随机光束时,像的侦测可能无法正常运作。" - }, - "image_detection_warning": { - "message": "本工具不支持像的侦测。" - }, - "non_simulateColors_warning": { - "message": "本工具只在「模拟色彩」模式下运作。" - }, - "brightness_note_popover": { - "message": "

只在「光线密度」够高时才有作用。

如需改变射出的光线数量,请调整全域性的「光线密度」滑杆。

" - }, - "refIndex_note_popover": { - "message": "

*于另一透光物内部时为相对值

如需模拟此物件之(绝对)折射率为 n₁,但其位于折射率为 n₀ 之另一透光物内部的情形,则此处折射率应设为 n₁/n₀ 。在更复杂的组合中,若多个透光物互相重叠,则重叠区域之等效折射率为个别折射率之乘积。

" - }, - "stepSize_note_popover": { - "message": "

用欧拉法求解光线程函方程(eikonal ray equation)的步长 - 更多资讯详见 'CircleGrinGlass.js' 中的 'step' 函数与原始码文件。

" - }, - "eps_CircleGrinGlass_note_popover": { - "message": "

单位 - [长度]^2.

本数值容忍度被用于 'CircleGrinGlass.js' 中的 'isOutsideGlass', 'isInsideGlass' 以及 'isOnBoundary' 函数。

" - }, - "eps_GrinGlass_note_popover": { - "message": "

单位 - [长度].

本数值容忍度被用于 'GrinGlass.js' 中的 'isOutsideGlass', 'isInsideGlass' 以及 'isOnBoundary' 函数。

" - }, - "cauchyCoeff": { - "message": "柯西系数" - }, - "transRatio": { - "message": "透光率" - }, - "applytoall": { - "message": "套用全部" - }, - "duplicate": { - "message": "复制" - }, - "delete": { - "message": "删除" - }, - "unselect": { - "message": "取消选取" - }, - "unselect_popover": { - "message": "取消选取此物件(在空白处按滑鼠右键也有相同的功能)" - }, - "showadvanced": { - "message": "更多选项…" - }, - "processing": { - "message": "处理中…… 按此处以终止。" - }, - "contribute": { - "message": "贡献" - }, - "github": { - "message": "GitHub" - }, - "about": { - "message": "关于" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/cn/about" - }, - "translate": { - "message": "协助我们翻译本程序" - }, - "translated": { - "message": "已翻译" - }, - "undo_popover": { - "message": "复原上个动作。(Ctrl+Z)" - }, - "redo_popover": { - "message": "重做上个动作。(Ctrl+Y)" - }, - "reset_popover": { - "message": "清空整个场景。" - }, - "save_popover": { - "message": "将目前场景存档。" - }, - "open_popover": { - "message": "打开文件或背景图片。背景图片将从坐标原点显示。(或拖放文件)" - }, - "get_link_popover": { - "message": "复制并前往本场景的专属网址,以便分享连结(可考虑透过短网址工具)。另见设定->自动同步网址。" - }, - "get_link_warning": { - "message": "本网址过长,在部分平台上可能无法正常运作。建议改用「保存」并分享文件。 " - }, - "export_svg_warning": { - "message": "导出为SVG:不支持混色与相对折射率低于1的情形。" - }, - "export_ray_count_warning": { - "message": "目前场景中的光线数量大于光线数量上限。 您可能需要将剪取框选项中的光线数量上限调高。" - }, - "view_gallery_popover": { - "message": "前往「作品集」页面以载入示例。" - }, - "tool_SingleRay_popover": { - "message": "由两点决定一条光线。(拖曳或点击以创建. 第一个点是光源,射向第二个点。)" - }, - "tool_Beam_popover": { - "message": "由一线段产生平行或发散光束,密度由「光线密度」滑杆决定。 (拖曳或点击以创建。)" - }, - "tool_PointSource_popover": { - "message": "由一点向四周发射光线,数量由「光线密度」滑杆决定。 (点击以创建。)" - }, - "tool_AngleSource_popover": { - "message": "指定发射角之点光源。" - }, - "tool_Mirror_popover": { - "message": "模拟光线射到镜子时的反射。(拖曳或点击以创建。)" - }, - "tool_ArcMirror_popover": { - "message": "圆弧形的镜子,由三点决定。(拖曳或点击以创建。前两个点定义弧形两边间的空隙,第三点决定弧的大小。)" - }, - "tool_ParabolicMirror_popover": { - "message": "抛物线形的镜子,由三点决定。(拖曳或点击以创建。)" - }, - "tool_CustomMirror_popover": { - "message": "形状为自订等式 y = f(x) 的镜子,其中 (x,y) 为变换过的座标,使得两控制点为 (-1,0) 及 (1,0)。 (拖曳或点击以创建。)" - }, - "tool_BeamSplitter_popover": { - "message": "能穿透一个比例的光的镜子。(拖曳或点击以创建。)" - }, - "tool_IdealMirror_popover": { - "message": "完全符合面镜公式(1/p + 1/q = 1/f)的理想化「曲面」镜,可直接设定其焦距。 (拖曳或点击以创建。)" - }, - "tool_PlaneGlass_popover": { - "message": "模拟光线经过透光物体界面时的反射与折射。(拖曳或点击以创建。)" - }, - "tool_CircleGlass_popover": { - "message": "圆形透光物,由圆心与表面上一点决定。(拖曳或点击以创建。)" - }, - "tool_CircleGrinGlass_popover": { - "message": "折射率为自定义函数 n(x,y),边界为圆形的透光物。(拖曳或点击以创建。)" - }, - "tool_Glass_popover": { - "message": "任何由线段与圆弧组成的透光物。 (点击以建立线段,拖曳以建立弧形,点击一开始的点以结束绘制。)" - }, - "tool_GrinGlass_popover": { - "message": "折射率为自定义函数 n(x,y),边界为多边形的透光物。警告:仅支持简单多边形,否则行为无法预测。(点击以建立线段,点击一开始的点以结束绘制。)" - }, - "tool_IdealLens_popover": { - "message": "完全符合薄透镜公式(1/p + 1/q = 1/f)的理想化透镜,可直接设定其焦距。 (拖曳或点击以创建。)" - }, - "tool_SphericalLens_popover": { - "message": "球面透镜。(点击以创建。)" - }, - "tool_CustomGlass_popover": { - "message": "形状为自订不等式 f(x) < y < g(x) 的透光物,其中 (x,y) 为变换过的座标,使得两控制点为 (-1,0) 及 (1,0)。 (拖曳或点击以创建。)" - }, - "tool_Blocker_popover": { - "message": "线段形状的吸光片,光线射到其上后就不会再射出。(拖曳或点击以创建。)" - }, - "tool_Aperture_popover": { - "message": "一对线段形状的吸光片,可用对称方式调整其孔洞的大小。(拖曳或点击两个端点以创建。)" - }, - "tool_CircleBlocker_popover": { - "message": "圆形遮光物,光线射到其上后就不会再射出。(拖曳或点击以创建。)" - }, - "tool_DiffractionGrating_popover": { - "message": "将光线依波长分割成不同角度的衍射光栅。 注意:衍射光的强度可能不准确。 (拖曳或点击以创建。)" - }, - "tool_Ruler_popover": { - "message": "指定原点与另一点。(拖曳或点击以创建。)" - }, - "tool_Protractor_popover": { - "message": "指定圆心和圆周上一点作为零度位置。刻度单位为度。(拖曳或点击以创建。)" - }, - "tool_Detector_popover": { - "message": "测量通过一线段的能量流率(P)、垂直动量流率(F⊥)与水平动量流率(F∥)。(拖曳或点击以创建该线段。)单位为任意。" - }, - "tool_Detector_info_popover": { - "message": "
  • P: 能量流率(通量),单位为 B/s(见下文)。
  • F⊥: 垂直动量流率,单位为 (B/s)/c。
  • F∥: 平行动量流率,单位为 (B/s)/c。
  • 导出的 CSV 中的辐照度单位为 (B/s)/L。
  • L 是本模拟器中使用的任意长度单位。
  • B 是辐射通量或光通量的任意单位,对应到「亮度」选项的单位:非朗伯光束为 B/L,点光源为 500B/360°。
  • 无量纲因子 s 是「设定」->「显示状态栏」中显示的「亮度尺度」,当「光线密度」高于某个阈值时为1,否则与「光线密度」成正比。
  • 如果某些光线在内反射的无穷级数中被截断,则总截断量将显示为误差估计。
" - }, - "tool_TextLabel_popover": { - "message": "文字标签。" - }, - "tool_LineArrow_popover": { - "message": "线段或箭头。(拖曳或点击以创建。)" - }, - "tool_Drawing_popover": { - "message": "手绘工具。(拖曳以绘图。)" - }, - "tool__popover": { - "message": "拖曳以移动视窗。(滑鼠右键拖曳也有相同的功能)" - }, - "mode_rays_popover": { - "message": "画出光线。当「光线密度」高时,光线呈现连续。 " - }, - "mode_extended_popover": { - "message": "除光线实际路径外,亦画出其延长线。橘色、灰色分别表示向后、向前的延长线。
若使用「模拟色彩」,则改以光源颜色显示并以虚线区分。" - }, - "mode_images_popover": { - "message": "点出像的位置。黄点表示实像,橘点表示虚像,灰点(图中没有)表示虚物。注意「光线密度」不够高时有些像无法正常显示。
若使用「模拟色彩」,则改以光源颜色显示并以点的大小区分。" - }, - "mode_observer_popover": { - "message": "模拟从某位置见到的光线与像。蓝色圆形为观察者,与其相交的光线被其「观察」到。观察者无法知道光线真正的起始位置,但若其在某处相交,它会认为光线是从该处来的。光线以蓝色表示,相交处以黄色(实像)或橘色(虚像)表示。 (拖曳大蓝点以移动观察者。)
若使用「模拟色彩」,则改以光源颜色显示。" - }, - "simulateColors_popover": { - "message": "模拟光源的颜色(波长)、混色、遮光物与镜子的滤光,以及透光物的色散。选取物件后可调整这些参数。重叠多条不同波长的光线可用于模拟光谱。屏幕显示之颜色仅为粗略近似,且当「光线密度」太高或太低时可能非常不准确。" - }, - "rayDensity_popover": { - "message": "决定从光束与点光源射出的光线数量。这也会影响到像的侦测与颜色渲染的准确性。" - }, - "showGrid_popover": { - "message": "决定是否显示背景网格。" - }, - "grid_popover": { - "message": "决定是否对齐网格。" - }, - "lockObjs_popover": { - "message": "决定物件是否能被移动。" - }, - "zoom_popover": { - "message": "通过百分比缩放视图。" - }, - "help_popover": { - "message": "限制拖曳行为

拖曳物件时,按住 Shift 以限制于水平或垂直移动;按住 Ctrl 以复制物件。建立线型物件或拖曳其端点时,按住 Shift 以锁定角度或吸附至 0°、45°、90°;按住 Ctrl 以对于中心点旋转或缩放。

群组、旋转及缩放物件

按住 Ctrl,点击多个控制点(如端点),并点击空白处以将这些点群组并建立控制杆。拖曳控制杆(或按方向键)以平移群组;Shift+拖曳以限制于水平或垂直移动;Ctrl+拖曳以旋转;Ctrl+Shift+拖曳以缩放。移动「+」以设定旋转或缩放中心。点击控制杆并按 Ctrl+D 以复制群组;按 Delete 以解散群组。

直接编辑座标

对控制点(如端点)点两下或按右键,输入 (x,y) 座标,然后按 Enter。

键盘快速键

当一物件在被选取的状态(被点击)时,按方向键以移动;Ctrl+D 以复制;Delete 以删除。

联络我们

建议使用 GitHub 上的 DiscussionsIssues 功能(请使用英文)。若您对 GitHub 不熟,也可发送电子邮件至 ray-optics@phydemo.app(可使用中文)。

也欢迎直接进行贡献(见贡献指南)。

" - }, - "show_help_popups": { - "message": "显示提示泡泡" - }, - "show_help_popups_popover": { - "message": "决定滑鼠移到按钮上方时是否显示提示泡泡(须重新载入网页以套用变更)" - }, - "show_json_editor": { - "message": "显示 JSON 编辑器Beta" - }, - "show_json_editor_popover": { - "message": "显示表达场景代码的 JSON 编辑器。在创建自定义模块时需要使用(见工具->其他->导入模块->创建自定义模块)。" - }, - "show_status": { - "message": "显示状态方块" - }, - "show_status_popover": { - "message": "显示状态方块,其中包含滑鼠座标,效能信息,以及被截断的亮度(光线在内反射的无穷级数中被截断的总亮度)。" - }, - "auto_sync_url": { - "message": "自动同步网址" - }, - "auto_sync_url_popover": { - "message": "启用时,网址会随着场景自动更新,而不必持续手动储存场景。如需设定标题,请用文件->保存->重命名。" - }, - "auto_sync_url_warning": { - "message": "本场景过大,无法与网址同步。 请自行储存场景。" - }, - "gridSize": { - "message": "网格大小" - }, - "observer_size": { - "message": "观察者大小" - }, - "language": { - "message": "语言" - }, - "close": { - "message": "关闭" - }, - "advanced_help": { - "message": "进阶说明详见右下角的说明图示。" - }, - "ray_count": { - "message": "光线片段数量:" - }, - "total_truncation": { - "message": "被截断的亮度:" - }, - "brightness_scale": { - "message": "亮度尺度:" - }, - "time_elapsed": { - "message": "花费时间(ms):" - }, - "force_stopped": { - "message": "已强制终止。" - }, - "mouse_coordinates": { - "message": "滑鼠座标:" - }, - "modules_tutorial": { - "message": "制作自定义模块" - }, - "modules_tutorial_url": { - "message": "https://phydemo.app/ray-optics/cn/modules/tutorial" - }, - "identical_optical_objects_warning": { - "message": "场景中有两个完全相同的光学元件完全重合。 这可能会导致非预期的行为。" - }, - "import_modules": { - "message": "导入模块..." - }, - "import_modules_title": { - "message": "导入模块" - }, - "modules_url": { - "message": "../cn/modules/modules.html" - }, - "remove_module": { - "message": "移除模块" - }, - "module_conflict": { - "message": "场景中已有一个同名但不相同的模块。您可以指定新的名称,或保留相同名称以取代原模块。" - }, - "brightness_inconsistent_warning": { - "message": "有至少两个光源的亮度以不一致的比例达到饱和。这可能会导致探测器的读数与色彩渲染错误。请提高光线密度或降低光源亮度。" - } -} \ No newline at end of file diff --git a/locales/zh-CN/gallery.json b/locales/zh-CN/gallery.json new file mode 100644 index 00000000..1b1b8d64 --- /dev/null +++ b/locales/zh-CN/gallery.json @@ -0,0 +1,486 @@ +{ + "galleryPage": { + "title": "“射线光学模拟”作品集", + "description": "以下列表为使用[“射线光学模拟”网页程序](/simulator)制作的互动式光学演示。欢迎您贡献新项目(请参阅[贡献指南](/contributing/gallery))。如发现内容有误,请[在GitHub上建立Issue](/github/issues)或发送电子邮件至[ray-optics@phydemo.app](/email)。", + "categories": { + "title": "类别", + "reflection": "光的反射", + "refraction": "光的折射", + "lens": "透镜", + "combinationOfLenses": "透镜组合", + "grinOptics": "渐变折射率光学", + "miscellaneous": "其他" + }, + "contributors": "贡献者:{{contributors}}", + "openInSimulator": "在模拟器中打开" + }, + "galleryData": { + "common": { + "warningthesequenceof": "警告:光线出现的顺序并不代表实际的光速。只有最终的图像有意义。" + }, + "imagesFormedByTwoMirrors": { + "title": "两面镜子成像", + "description": "本模拟项目显示了两面镜子所成的像,其中绿色的 L 为物。若两面镜子的夹脚为 \\(\\frac{360^\\circ}{n}\\) 那么将成\\(n-1\\) 个虚像(橘色的 L)。可拖曳镜子端点来改变夹角。" + }, + "parabolicMirror": { + "title": "抛物面镜", + "description": "此模拟演示了抛物面镜的聚焦特性。" + }, + "hyperbolicMirror": { + "title": "双曲面镜", + "description": "本模拟演示了双曲面镜的反射特性:从一个焦点向双曲面镜传播的光线将如同从另一个焦点射出。\n\n双曲面的两个焦点是等光程点(请参阅[ 等光程点](/gallery/aplanatic-points))。", + "theorangeraysareimag": "橙色线是黄色反射光线的延长线。\n这些虚射线在另一个焦点上汇合。", + "pointlightsourceaton": "位于一个焦点的点光源" + }, + "retroreflectors": { + "title": "回复反射器", + "description": "这是两种回复反射器的模拟:\n\n1. 角隅反射器。\n2. 猫眼回复反射器。", + "dragtorotatethebeam": "拖曳此处\n可旋转光束", + "catseyeretroreflecto": "猫眼回覆反射器", + "cornerretroreflector": "角隅反射器" + }, + "periscope": { + "title": "潜望镜", + "description": "这是一个由两面平镜和一些光线阻挡器制成的潜望镜模拟。", + "observerseyenottosca": "观察者的眼睛(非按比例)" + }, + "newtonianTelescope": { + "title": "牛顿望远镜", + "description": "这是一个配有Plössl目镜的牛顿望远镜模型。" + }, + "penroseUnilluminableRoom": { + "title": "无法照亮的彭罗斯房间", + "description": "无法照亮的彭罗斯房间由椭圆形、圆形和线性镜子构成。它有一个有趣的特性,即房间内的一个点源(绿色)无论放在哪里,都不会照亮整个房间。您可以拖动绿色点以移动源。", + "nomatterwhereyouputt": "无论您将点光源放在哪里,它都不会照亮整个房间。\n警告:由于数值误差,可能会在一段时间后仍然照亮。" + }, + "opticalCavity": { + "title": "双镜共振腔", + "description": "模拟由两面镜子组成的共振腔。假设腔体的长度为\\(d\\),其镜子的曲率半径分别为\\(R_1\\)和\\(R_2\\)(根据惯例,\\(R>0\\)为凹面镜),那么只有当\\(0\\leq (1-\\frac {d}{R_1})(1-\\frac {d}{R_2})\\leq 1\\)时,共振腔才会稳定(这意味着从一面镜子向另一面镜子发出的每一道光线都保证有非发散的轨迹,前提是镜子的反射率足够高)。在此模拟中,我们假设镜子是理想曲面镜,这意味着\\(f=\\frac{R}{2}\\),将先前的稳定条件变为\\(0\\leq (1-\\frac {d}{2f_1})(1-\\frac {d}{2f_2})\\leq 1\\)。 [这里](/gallery/resonator)有一个使用球面镜的类似模拟,在抛物面近似下,第一种稳定条件成立。", + "clickholdleftmouseto": "点击 + 按住左键\n以移动光线", + "dragtomovetheidealmi": "拖曳此处\n可水平移动镜子", + "d400intheresonatorsb": "下方的共振腔中d = 400", + "confocalresonator": "焦聚共振腔", + "concentricresonator": "共心共振腔", + "concaveconvexresonat": "凹凸共振腔", + "planoconcaveresonato": "平凹共振腔" + }, + "resonator": { + "title": "平凹共振腔", + "description": "这是一个平凹共振腔的演示。如果镜子间的距离大于曲率半径,共振腔将会不稳定。如果镜子间的距离小于或等于曲率半径,就会形成稳定的共振腔模式。", + "flatmirror": "平面镜", + "sphericalconcavemirr": "球形凹面镜", + "unstableresonator": "不稳定的共振腔", + "stableresonator": "稳定的共振腔" + }, + "mazeSolution": { + "title": "用一条光线解迷宫", + "description": "此模拟中,一条光线在迷宫内部产生,并被墙壁多次反射。迷宫内的大红色和小红色正方形(如下面的截图所示)分别代表光线的起源和初始方向。取决于光线初始方向,光线可能最终会离开迷宫,因此原则上可以通过追踪光线的路径计算出迷宫的解法。", + "controltherayorigina": "通过分别拖曳此两标记\n以调整光线的初始点与方向。", + "notethatthesimulatio": "请注意,只有当左下角的“处理中…”\n消失时,才代表模拟完成。", + "mazeexit": "迷宫出口" + }, + "specularAndDiffuseReflection": { + "title": "镜面反射与漫反射", + "description": "同一束光线照射在光滑表面和粗糙表面上,展示了镜面反射与漫反射之间的区别。", + "specular": "镜面反射", + "diffuse": "漫反射" + }, + "chaffCountermeasure": { + "title": "干扰箔", + "description": "这是一个箔片反射对雷达效应的定性模拟(忽略衍射效应)。", + "plane": "飞机", + "radar": "雷达", + "chaff": "箔片", + "selectthechafftochan": "选择箔片可改变箔片数量(N)和长度(L)。" + }, + "causticsFromAReflectiveSphere": { + "title": "反射性球体的焦散", + "description": "一个反射性的积分球。也可以是液滴(如雨滴)中的反射。移动点光源的位置可以看到许多漂亮的图样。", + "movethepointsourcear": "移动点光源以观看焦散及节点\n在积分球中是如何变换的。\n改变遮光物的大小与位置,\n以及球的开口大小来观察更多效果。" + }, + "theMirascope": { + "title": "幻象镜", + "description": "**幻象镜** 是一种有趣的光学幻觉演示装置,它利用两个面对面的抛物面镜来产生一个立体悬浮影像的幻觉。该装置由以下部件构成:\n1. **两个抛物面镜**:大小完全相同,一个朝上,一个朝下,形成贝壳状结构。这些镜子被设计成让光聚焦于特定点。顶部的镜子在其顶点处有一个孔,让光线进入装置。\n2. **一个小物体**:放置在幻象镜内,通常位于顶部镜子的焦点附近,其非常接近底部镜子的顶点。\n\n当来自物体的光线在两个镜子之间反射时,它的方向会改变为形成一个看似逼真、立体的影像,悬浮于幻象镜的表面上方。这种幻象如此逼真,人们常常试图触摸影像,结果发现什么也没有。\n\n幻象镜被广泛用于科学演示、玩具及新奇物品,以说明光学中反射和光线行为的原理。", + "object1": "物体", + "realimage1": "实像" + }, + "reflect": { + "title": "反射与折射", + "description": "此模拟显示了光经过界面的反射和折射。" + }, + "internalReflection": { + "title": "全反射", + "description": "此模拟显示了光经过界面的折射和内部反射,包括全反射。" + }, + "prisms": { + "title": "稜鏡", + "description": "此模拟演示了直角稜鏡(right-angle prism)、波罗稜鏡(Porro prism)、菱形稜鏡(rhomboid prism)、杜福稜鏡(Dove prism),和五面稜鏡(pentaprism)。", + "rhomboid": "菱形", + "rightangle": "直角", + "porro": "波罗", + "dove": "杜福", + "pentaprism": "五面" + }, + "beamDirectors": { + "title": "光束导向器", + "description": "这是一个普通双棱镜 (biprism) 和菲涅耳双稜鏡(Fresnel biprism)的模拟。双棱镜可以将入射的平行光束导向两个方向,其取决于顶角的大小。", + "thisfresnelbiprismwa": "这个菲涅耳双稜鏡是由上面的双稜鏡制成\n您可以选择双稜鏡并调整 N_silce(切片数量)参数。", + "fresnelbiprism": "菲涅耳双稜鏡", + "biprism": "双稜鏡" + }, + "apparentDepth": { + "title": "视深度", + "description": "当您从空气中观察水下的物体时,物体的深度会看似小于其实际深度。本模拟演示了这种由光的折射造成的现象。视深度与观察者的位置有关,这点我们可以通过拖动蓝色圆圈来演示。", + "observedimageorange": "观察到的像(橘点)", + "observer": "观察者", + "objectunderwatergree": "水中物体(绿点)" + }, + "bendedPencil": { + "title": "弯曲的铅笔", + "description": "从上方观察部分浸入水中的铅笔,因为空气和水之间的折射率的不连续性,我们的眼睛会感觉到铅笔看起来既断裂又弯曲。然而,在这个模拟中,弯曲的现象更为明显。您可以查看断裂的铅笔模拟,那里的断裂现象更为明显。", + "bentpencilyellowimag": "弯曲的铅笔(黄色)\n视网膜上的影像", + "dielectricmaterial": "电介质材料", + "originalpencilgreen": "原始铅笔(绿色)", + "observerseye": "观察者的眼睛", + "ignoretheorangesquar": "忽略橙色的正方形!" + }, + "brokenPencil": { + "title": "断裂的铅笔", + "description": "从侧面观察部分浸入水中的铅笔,因为空气和水之间的折射率的不连续性,我们的眼睛会感觉到铅笔看起来既断裂又弯曲。然而,在这个模拟中,断裂的现象更为明显。您可以查看弯曲的铅笔模拟,那里的弯曲现象更为明显。", + "brokenpencilyellowim": "断裂的铅笔(黄色)\n视网膜上的影像" + }, + "chromaticDispersion": { + "title": "色散", + "description": "这个模拟使用一个白色光束和一个三角稜鏡展示色散现象。此处白色是由红、橙、黄、绿、青、蓝、紫的混色形成的。", + "dragheretoadjustbeam": "拖曳此处\n可调整光束宽度", + "dragheretorotatethep": "拖曳此处\n可旋转棱镜" + }, + "rainbows": { + "title": "彩虹", + "description": "本模拟演示了虹、霓以及亚历山大暗带是如何形成的。这里,我们以红、橙、黄、绿、青、蓝、紫的混色来近似阳光的光谱。对于虹/霓,离开雨滴的光线是由雨滴内部的一次/两次内部反射产生的(你可以通过将光线密调低并拖动雨滴来观察这一点)。请注意,这些并不是全内反射,因此出射光线的强度远低于入射光线。由于[最小偏向角](/gallery/minimum-deviation-angle)与波长有关,不同颜色的光线会在不同的角度堆积,于是彩虹中的颜色就产生了。远离最小偏向角时,光线不会堆积,所以所有颜色都很弱并混合在一起,使得在两彩虹之外的角度产生昏暗的白色(或“灰色”)。相较之下,虹与霓之间则没有这样的光线,于是形成亚历山大暗带。", + "thesearethecolorspro": "以上是由单个雨滴产生的颜色。\n我们最终看到的彩虹是由天空中大量的雨滴产生的,\n每个都对观察者呈现单一一种颜色(在相应的角度)。", + "secondaryrainbow": "霓", + "alexandersdarkband": "亚历山大暗带", + "raindrop": "雨滴", + "primaryrainbow": "虹", + "sunlight": "阳光" + }, + "minimumDeviationAngle": { + "title": "最小偏向角", + "description": "光线射到光学元件上的偏向角有多种定义。下方的截图中可以看到对于三棱镜和球形透镜的定义。在本模拟中,光线进入光学元件的入射角与偏向角之间的关系在某个角度有局部极小值,这个偏向角被称为“最小偏向角”。这个局部极小值可以解释如[彩虹](/gallery/rainbows)和光晕这样的光学现象。由于这个局部极小值,偏转的光线在特定的方向上堆积,产生“光学焦散”(如在模拟中的例子C中看到的)我们会将其视为彩虹/光晕。", + "inexamplesaandbbyrot": "在例A和B中,通过在点A1到A2和B1到B2之间旋转稜鏡,改变光线进入光学元件的\n入射角,你可以清楚地看到一个最小的\n偏向角出现在两点之间的某处。\n(在例A中,偏向角为相对于水平轴测量,而在例B中,\n偏向角为相对于垂直轴测量)。\n现在请看例C(可用缩放功能拉近),并将两束光扩展(红色和紫色,\n重叠部分呈现粉红色。这与例B中旋转棱镜\n的效果相同,故是在改变入射角),并观察从点\nC1到C2之间的反向出射光线向下堆积于两个明显的红色和紫色\n线(“光学焦散”)- 最小偏向角出现在点C2附近,并与\n光的波长(颜色)有关。然后,把光束从C2扩展到C3时,它们的\n反向出射光线的方向反转为向上。", + "examplea": "例A", + "examplec": "例C", + "exampleb": "例B", + "dragtorotate": "拖曳以旋转", + "dragtoadjustbeamwidt": "拖曳以调整光束宽度", + "usethebuiltinzoomtob": "建议使用模拟器内建的缩放功能以利观察", + "deviationangle": "偏向角", + "incidenceangle": "入射角" + }, + "aplanaticPoints": { + "title": "等光程点", + "description": "光学系统的等光程点是其光学轴上的特殊点,即“从其中一点发出的光线会汇聚到另一点,或看似从从该点发散”。\n\n- 椭圆:椭圆镜片/镜子的两个焦点是等光程点,因为从一个焦点发出的光将汇聚向另一点。\n- 球体:球形透镜有两个等光程点,分别在球内和球外 - 更多细节请见模拟。\n- 双曲线:在[双曲面镜](/gallery/hyperbolic-mirror)模拟中的两个焦点也是等光程点。\n\n给定两个拥有水平座标 \\(x_1\\) 和 \\(x_2\\) 、具有相同垂直座标的点,并且设光学元件外部和内部的折射率分别为 \\(n_1\\) 和 \\(n_2\\),则若这两点要成为等光程点,我们的光学元件的边界必须满足\\begin{equation}k_1 n_1 \\sqrt{ (x - x_1)^2 + y^2} + k_2 n_2 \\sqrt{ (x - x_2)^2 + y^2} = E\\end{equation}使得 \\(k_i=1\\) 或 \\(-1\\)(取决于连接 \\(x_i\\) 和我们的光学元件边界的光线是实的或虚的),而 \\(E\\) 是一个使这个方程有非平凡解的常数。这个方程(可以用费马原理推导出来)是笛卡尔卵形线的方程(圆锥曲线是其特例)。", + "clickontheextendedra": "点选“延长光线”按钮以验证从球面镜片中的光源(点 A)发出的光,\n是从球面镜片外的光学轴上的另一点(点 B)发散,无球面像差。\n点 A 和 B 是球体的等光程点的例子。对于此点,在标记的 Y 轴的相对座标中(k1, k2, n1, n2, x1, x2, E)=(1, -1, 1.5, 1, 3 * 20, -4.5 * 20, 0),\n其中 x1,x2 是点 A,B 的水平座标(每个网格单元的尺寸为 20x20)。\n同样地,椭圆的焦点(点 C 和 D)是椭圆的等光程点的例子,对于此点(k1, k2, n1, n2, E)=(1, 1, 1.5, 1.5, > 0)", + "sphericallens": "球面透镜", + "ellipticallens": "椭圆透镜", + "yaxis": "Y 轴" + }, + "concaveLens": { + "title": "凹透镜", + "description": "模拟凹透镜使光束分散的现象。" + }, + "convexLens": { + "title": "凸透镜", + "description": "模拟凸透镜使光束聚焦的现象。" + }, + "lensImages": { + "title": "透镜成像", + "description": "模拟理想透镜成像,包括平行光与点光源成的像。" + }, + "transverseAndLongitudinalMagnification": { + "title": "横向和纵向放大率", + "description": "模拟焦距为 \\(f\\) 的理想透镜的横向和纵向放大率。横向(也称为线性)和纵向的放大率分别是 \\(M_T=1-\\frac{u}{f}\\) 和 \\(M_L=\\frac{dv}{du}\\),其中 \\(u\\) 和 \\(v\\) 分别是物体和图像距离我们的理想透镜的距离。另外,对于理想透镜,\\(M_L=-(M_T)^2\\)", + "inthisexamplewehavey": "在这个例子中,我们有 y'_j - y'_k = M_T * (y_j - y_k),其中 j,k∈{0,1,2,3,4,5}。\n因此,例如点物体(x_0,y_0)的横向放大率是 M_T = -3,我们可以计算 -\n(x'_0 - x'_1)/(x_1 - x_0) ≈ -0.3699\n(x'_0 - x'_2)/(x_2 - x_0) ≈ -0.7297\n(x'_0 - x'_3)/(x_3 - x_0) ≈ -1.4211\n(x'_0 - x'_4)/(x_4 - x_0) ≈ -2.4545\n(x'_0 - x'_5)/(x_5 - x_0) = -5.4\n.\n.\n.\n(这个比值将趋近于纵向放大率:M_L = - (M_T)^2 = -9)", + "rightclickonarealobj": "在(实)物上点击右键以查看其座标。\n绿色的方块是实际的点光源,黄色的方块是像。" + }, + "vanishingPoint": { + "title": "消失点", + "description": "有些光学系统将无限的平行线映射到影像平面上的一些线,使得这些线在一个点上相交,于是产生一种平行线在“无穷远处”相交的幻觉。这个交点被称为消失点。\n\n考虑一个由焦距为 \\(f\\) 的理想透镜组成,位于 \\(XY\\) 平面上,光学轴与 \\(X\\)(水平)轴重合,透镜与 \\(Y\\) 轴重合的光学系统。对于斜率为 \\(m\\) ,位于 \\(x<0\\) 的线,其消失点之 \\((x,y)\\) 座标为 \\((f,m f)\\) 。", + "youcanverifythatapai": "你可以验证一对斜率为 m 的平行线,经过理想透镜收敛到座标 (f,m∙f),\n通过点击“网格”按钮,并注意到每个网格单元的尺寸为20乘以20。\n你也可以验证改变理想透镜的焦距 f 时,收敛点(消失点)会如何受到影响。", + "thesepairofparallell": "这对平行线聚集到点B", + "thesepairofparallell1": "这对平行线聚集到点A", + "notethatthesepairsof": "注意这些平行线实际上并不是无穷大。" + }, + "monochromaticAberrations": { + "title": "单色像差", + "description": "这是不同单色像差的模拟:\n\n1. 球面像差(Spherical aberration)。\n2. 彗形像差(Coma aberration)。\n3. 散焦像差(Defocus aberration)。\n4. 场曲像差(Field curvature aberration)。", + "defocusaberration": "散焦像差", + "sphericalaberration": "球面像差", + "screen": "屏幕", + "fieldcurvatureaberra": "场曲像差", + "commaaberration": "彗形像差" + }, + "chromaticAberration": { + "title": "色像差", + "description": "此模拟显示了球面透镜的色像差(Chromatic aberration)。这里的白色是由红、橙、黄、绿、青、蓝、紫混色形成的。红光的焦距最大,而紫光的焦距最小。", + "dragtoadjustbeamwidt1": "拖拽此处可调整光束宽度" + }, + "hyperbolicLens": { + "title": "双曲透镜", + "description": "这是双曲透镜与球面透镜的对比。这两个透镜有相同的焦距,但双曲透镜可以将单色光的平行光束集中到一点(忽略光的波动性 - 也就是在几何光学的近似下)而不像球面透镜会有有球面像差(Spherical aberrations)。", + "thefocallengthofthis": "此球面透镜的焦距(在近轴近似中)为:\nf=R/(n-1)=200/(1.5-1)=400", + "thefocallengthofthis1": "此双曲透镜的焦距是:\nf = |C| ∙ sqrt(n^2 - 1) / (n - 1) = K ∙ sqrt(0.8) ∙ sqrt(1.5^2 - 1) / (1.5 - 1) = 400\n此双曲透镜的方程式是:\ny(x) = (a/K) - sqrt( ((x/K)^2 + (C/K)^2) / (n^2 - 1) )\n= 1.5 - sqrt( (0.8 + (x / 200)^2) / (1.5^2 - 1) )\n使得K是方程式维度与网格维度之间的转换常数 - 对于这个双曲面镜,K=20\n(例如0 0\\) 且\\(\\alpha = \\arctan k\\) 为等角螺线与同心圆形的交点上两切线的固定夹角,见[这个](https://en.wikipedia.org/wiki/Logarithmic_spiral#/media/File:Logspiral.gif)动画)的折射率函数为\\(n(r) ∝ \\frac{1}{r} \\) (这可用将光线路径以极座标表示并使用费马原理来证明)。", + "thecircularblockeris": "中央的圆形遮光物是为了\n避开折射率的奇异点", + "dragtochangetheiniti": "拖动此处可改变\n光线的初始方向", + "youcanselectthegring": "您可以选择渐变折射率透光物\n并更改数值求解器的步长" + }, + "luneburgLens": { + "title": "龙勃透镜", + "description": "龙勃透镜(Luneburg lens)是一个球形介电材料,折射率为 \\(n(\\rho) = \\sqrt{n_0-(\\frac{\\rho}{R})^2} \\),其中 \\(n_0=2\\) 是其球心的折射率,\\(R=100\\) 是球的半径,\\(\\rho\\) 是与球心的距离。\n\n上方的介电材料为由 \\(N=20\\) 个同心球组成的龙勃透镜,半径 \\(R_i=5(N+1-i)\\),折射率 \\(n_i = \\sqrt{n_0-(\\frac{R_i}{R})^2} \\),其中 \\(i=1,...,N\\)。然而,由于此模拟器会将互相重叠的光学元件的折射率相乘,所以第 \\(i\\) 个同心球形镜的数值折射率为 \\(n_{i}^\\text{numerical}=\\frac{n_i}{n_{i-1}}\\)。\n\n下方的介电材料是折射率为\\(n(r)\\)的渐变折射率材料。", + "approximatedmultilay1": "用多层近似的龙勃透镜(您可以选择并更改层数 N)", + "classicalluneburglen": "正统的龙勃透镜(您可以选择并更改数值求解器的步长)" + }, + "maxwellFisheyeLens": { + "title": "麦克斯韦鱼眼透镜", + "description": "麦克斯韦鱼眼透镜(Maxwell fisheye lens)是一个球形介电材料,折射率为 \\(n(\\rho) = \\frac{n_0}{1+(\\frac{\\rho}{R})^2} \\),其中 \\(n_0=2\\) 是其球心的折射率,\\(R=100\\) 是球的半径,\\(\\rho\\) 是与球心的距离。\n\n上方的介电材料为由 \\(N=20\\) 个同心球组成的麦克斯韦鱼眼透镜,半径 \\(R_i=5(N+1-i)\\),折射率 \\(n_i = \\frac{n_0}{1+(\\frac{R_i}{R})^2} \\),其中 \\(i=1,...,N\\)。然而,由于此模拟器会将互相重叠的光学元件的折射率相乘,所以第 \\(i\\) 个同心球形镜的数值折射率为 \\(n_{i}^\\text{numerical}=\\frac{n_i}{n_{i-1}}\\)。\n\n下方的介电材料是折射率为\\(n(r)\\)的渐变折射率材料。", + "approximatedmultilay2": "用多层近似的麦克斯韦鱼眼透镜(您可以选择并更改层数 N)", + "classicalmaxwellfish": "正统的麦克斯韦鱼眼透镜(您可以选择并更改数值求解器的步长)" + }, + "branchedFlow": { + "title": "分支流", + "description": "当光线经过折射率在空间上有随机扰动(相关长度远大于光的波长)的介质时,会形成一种类似树状的图案,称为分支流。本模拟使用一些余弦函数的和作为折射率函数来演示这个现象,其中余弦函数的振幅、波数与相位都是类似随机的数。" + }, + "singleRayDemo": { + "title": "单一光线演示", + "description": "本模拟演示了一条光线的反射和折射。" + }, + "sphericalLensAndMirror": { + "title": "球面透镜与面镜", + "description": "这个模拟演示了一束连续的光线穿过一个球面透镜和一个球面面镜。" + }, + "interrogationRoom": { + "title": "审讯室", + "description": "这是一个审讯室双向镜的模拟。在黑暗的房间里的观察者(理想情况下,黑暗的房间内部不会发出/反射光,同时会吸收来自审讯室的所有入射光)能够通过双向镜看到审讯室内部,因为审讯室里的灯产生的光被散射并由观察者接收,而嫌疑人只能看到审讯室内部以及他/她和灯的反射(因为嫌疑人未从黑暗的房间接收到光)。", + "pressonallimagestose": "按下“所有像”以查看\n灯的反射以及嫌疑人和观察者\n构成的的影像平面中物体的位置", + "darkroom": "黑暗的房间", + "twowaymirror": "双向镜", + "lamp": "灯", + "interrogationroom": "审讯室", + "observerseyeris": "观察者的眼睛", + "suspectseyeris": "嫌疑人的眼睛", + "thelampobjectinthesu": "嫌疑人的影像平面中的灯物体", + "thelampsreflectionin": "嫌疑人的影像平面中的灯的反射", + "thelampsreflection": "灯的反射", + "thelampobjectintheob": "观察者的影像平面中的灯物体" + }, + "cameraObscura": { + "title": "暗箱", + "description": "这是一个暗箱的模拟。在黑暗的房间里的观察者看到的是外面物体的倒置影像,并且这个影像是直接投影在他/她前面的墙壁上的(无需使用额外的透镜)。", + "observer2": "观察者", + "objectsoutside": "外面的物体", + "darkroom1": "黑暗的房间" + }, + "thePrincipleOfCameraImaging": { + "title": "相机成像原理", + "description": "本模板提供了一种交互式方法来学习相机成像原理,涵盖焦距、光圈、传感器灵敏度和背景模糊等基本主题,对学生和爱好者都有帮助。", + "camera": "相机", + "cmos": "CMOS" + }, + "nlSimulation": { + "title": "NL 双筒望远镜", + "description": "这个模拟展示了 Swarovski NL 双筒望远镜的粗略草图。" + }, + "einsteinRingRefocusedToSingleImageViaEyepiece": { + "title": "经由目镜将爱因斯坦环重新聚焦为单一影像", + "description": "这是一个目镜/透镜的模型,可以用在任何科学望远镜上,透过逆转“光晕”,将爱因斯坦环聚焦回原始形态,同时散射用来创建环的星体或大质量物体的光。" + }, + "blackCatBecomesWhite": { + "title": "「黑猫变白猫」演示", + "description": "「黑猫变白猫」是一个科普演示。当图画浸入水中时有部分会消失。制作步骤如下:\n\n1. 在纸上绘制图案(如黑猫)。\n2. 将纸放入塑胶套中。\n3. 在塑胶套上描出该图案的一部分(如猫的边框)或其他图案。当放入水中时,绘制在纸上的图案将消失,但绘制在塑胶套上的图案不会消失。\n\n本模拟解释它的原理。", + "whenthebagisunderwat": "当塑胶套在水中时,来自纸上的光无法到达眼睛,\n故我们只看到画在塑胶套上的图案。", + "lightfromtheplastics": "来自塑胶套上的光", + "lightfromthepaper": "来自纸上的光", + "eyes": "眼睛", + "dragtomovethebagouto": "拖曳此处可将塑胶套移出水面" + }, + "dichroicRbgSplitterAndCombiner": { + "title": "二色性RGB分光器与合光器", + "description": "这个模拟使用二色镜来分割和组合RGB光束。", + "rgbcomponentsplitter": "RGB分量分光器与合光器", + "lightsource": "光源", + "dichroiccube": "二色性立方体", + "beamcombiner": "合光器" + }, + "ganBasedLcdPixel": { + "title": "液晶显示器像素", + "description": "这是一个液晶显示器像素的模型。它模拟了新型的微型发光二极体显示层的功能,以及我们的眼睛是如何感知它的。", + "pixelsaresosmallthel": "由于像素非常小,光\n在我们的眼中看起来是混合的", + "changetherateoftrans": "改变透光率\n来产生任何RGB值", + "blueledbacklight": "蓝色LED背光", + "yellowphosphor": "黄色磷光体", + "liquidcrystal": "液晶", + "lightfilters": "滤光器", + "pixelasvisibletoview": "观察者看到的像素", + "notpartoflcddisplay": "不是液晶显示器的一部分" + }, + "concaveMirrorWearableDisplay": { + "title": "凹面镜可穿戴显示器", + "description": "简易的可穿戴显示器。许多设计都使用两个镜子及一个正透镜,但本模拟为只用一个光学元件的版本。比例约为5:1mm。\n\n< p>CC0:此作品已被标记为释出至公有领域", + "tft09display": "TFT 0.9吋显示屏", + "concavemirror": "凹面镜", + "eye1": "眼睛", + "nose": "鼻子", + "pointsourcetomeasure": "用来测量半径的点光源", + "t15readingglasses": "+1.5度阅读眼镜" + }, + "reflectingMonochromator": { + "title": "反射式单色仪", + "description": "这是一个反射式单色仪的模拟,其透过反射式衍射光栅与聚焦处的出射口,从多波长混合的光之中取得窄频宽的光。", + "reflectingmonochroma": "反射式单色仪", + "rotatediffractiongra": "旋转衍射光栅\n以从多波长混合的光\n之中取得窄频宽的光", + "exitslitmonochromati": "出射口\n\n单色光" + }, + "solarEclipses": { + "title": "日食", + "description": "本模拟演示了不同类型的日食。右上方的图中,月球的影子遮蔽了太阳,在中心产生了日全食,周围地区则是日偏食。右下方的图为日环食,其中由于月球距离地球较远,无法完全遮蔽太阳,在中心留下一个明亮的环(本二维模拟器中,这个“环”为阳光只来自太阳的最上方与最下方的部分),而周围地区也是日偏食。", + "nottoscale": "(非按比例)", + "sun": "太阳", + "moon": "月亮", + "partialeclipse": "日偏食", + "annulareclipse": "日环食", + "earth": "地球", + "totaleclipse": "日全食" + }, + "moduleExampleBasics": { + "title": "模块示例 - 基本概念", + "thistextisinexamplem": "这段文字在 ExampleModule 中", + "thistextisalsoinexam": "这段文字也在 ExampleModule 中", + "thistextisnotinamodu": "这段文字不在模块中。", + "thistextisalsonotina": "这段文字也不在模块中。" + }, + "moduleExampleParameters": { + "title": "模块示例 - 参数", + "thismodulehastwopara": "本模块有两个参数:n=`n`与theta=`theta`。\n您可以选取并拖曳数值滑杆来调整它们。", + "thesizeofthistextosc": "这段文字的大小会随theta震荡。" + }, + "moduleExampleControlPoints": { + "title": "模块示例 - 控制点", + "hereisthefirstdragga": "↙这是本模块的第一个(可被拖曳的)控制点", + "hereistheseconddragg": "↙这是本模块的第二个(可被拖曳的)控制点", + "hereisthemidpoint": "↙这是中间点" + }, + "moduleExampleArraysAndConditionals": { + "title": "模块示例 - 数组与条件", + "a1darrayii": "一维数组:i=`i`", + "thistextisshownonlyw": "这段文字只在n>5时显示" + }, + "moduleExampleCustomEquation": { + "title": "模块示例 - 自定义数学式", + "amirrorofshapeycos2p": "形状为 y=cos(2 pi x + `phi`) 的镜子" + }, + "moduleExampleShapeParametrization": { + "title": "模块示例 - 形状参数化", + "alensdefinedbydr1r2": "以 d, R_1, R_2 定义的透镜", + "alensdefinedbydffdbf": "以 d, FFD, BFD 定义的透镜" + } + } +} \ No newline at end of file diff --git a/locales/zh-CN/main.json b/locales/zh-CN/main.json new file mode 100644 index 00000000..5caa6420 --- /dev/null +++ b/locales/zh-CN/main.json @@ -0,0 +1,229 @@ +{ + "meta": { + "languageName": "简体中文", + "parentheses": "{{main}}({{sub}})", + "colon": "{{name}}:{{value}}", + "list": "{{first}}、{{others}}" + }, + "project": { + "name": "射线光学模拟", + "shortName": "射线光学", + "description": "自由、开源的网页程序,用于建立及模拟二维几何光学场景。" + }, + "pages": { + "simulator": "模拟器", + "home": "首页", + "gallery": "作品集", + "modules": "模块", + "about": "关于", + "github": "GitHub" + }, + "homePage": { + "description": "建立二维几何光学场景,并实时模拟光线行为。\n完全免费,免下载,源代码[公开于 GitHub](/github)。", + "launchSimulator": "启动程序" + }, + "tools": { + "title": "工具", + "categories": { + "lightSource": "光源", + "mirror": "镜子", + "glass": "透光物", + "blocker": "遮光物", + "other": "其他" + }, + "common": { + "clickInstruction": "点击以创建。", + "lineInstruction": "拖曳或点击以创建。", + "circleInstruction": "拖曳或点击以创建,第一点为圆心,第二点于圆周上。" + }, + "SingleRay": { + "title": "单一光线", + "description": "由两点决定一条光线。", + "instruction": "拖曳或点击以创建,第一个点是光源,射向第二个点。" + }, + "Beam": { + "title": "光束", + "description": "由一线段产生平行或发散光束,密度由「光线密度」滑杆决定。" + }, + "PointSource": { + "title": "点光源", + "description": "由一点向四周发射光线,数量由「光线密度」滑杆决定。" + }, + "AngleSource": { + "instruction": "拖曳或点击以创建,第一个点是光源,射向第二个点。", + "description": "指定发射角之点光源。" + }, + "Mirror": { + "title": "线段", + "description": "模拟光线射到镜子时的反射。" + }, + "otherMirror": { + "title": "曲线", + "description": "曲线形的镜子。可选圆弧、抛物线,或自定义函数 y = f(x)。" + }, + "ArcMirror": { + "title": "圆弧", + "description": "圆弧形的镜子,由三点决定。", + "instruction": "拖曳或点击两个端点以创建,然后点击弧上另一点以决定曲率。" + }, + "ParabolicMirror": { + "title": "抛物线", + "description": "抛物线形的镜子,由三点决定。", + "instruction": "拖曳或点击两个端点以创建,然后点击顶点。" + }, + "CustomMirror": { + "title": "自定义函数", + "description": "形状为自订等式 y = f(x) 的镜子,其中 (x,y) 为变换过的座标,使得两控制点为 (-1,0) 及 (1,0)。" + }, + "IdealMirror": { + "title": "理想曲面镜", + "description": "完全符合面镜公式(1/p + 1/q = 1/f)的理想化「曲面」镜,可直接设定其焦距。" + }, + "BeamSplitter": { + "title": "分光镜", + "description": "能穿透一个比例的光的镜子。" + }, + "PlaneGlass": { + "title": "半平面", + "description": "模拟光线经过透光物体界面时的反射与折射。", + "instruction": "拖曳或点击界面上的两点以创建。" + }, + "otherGlass": { + "title": "其他形状", + "description": "任何由线段与圆弧组成的透光物,或自定义不等式 f(x) < y < g(x)。" + }, + "CircleGlass": { + "title": "圆形", + "description": "圆形透光物,由圆心与表面上一点决定。" + }, + "Glass": { + "title": "多边形 / 圆弧", + "description": "任何由线段与圆弧组成的透光物。", + "instruction": "点击以建立线段,拖曳以建立弧形,点击一开始的点以结束绘制。" + }, + "CustomGlass": { + "title": "自定义函数", + "description": "形状为自订不等式 f(x) < y < g(x) 的透光物,其中 (x,y) 为变换过的座标,使得两控制点为 (-1,0) 及 (1,0)。" + }, + "IdealLens": { + "title": "理想透镜", + "description": "完全符合薄透镜公式(1/p + 1/q = 1/f)的理想化透镜,可直接设定其焦距。" + }, + "SphericalLens": { + "title": "球面透镜", + "description": "球面透镜,其形状可用多种方式定义。" + }, + "CircleGrinGlass": { + "title": "渐变折射率圆形", + "description": "折射率为自定义函数 n(x,y),边界为圆形的透光物。" + }, + "GrinGlass": { + "title": "渐变折射率多边形", + "description": "折射率为自定义函数 n(x,y),边界为多边形的透光物。", + "instruction": "点击以建立线段,点击一开始的点以结束绘制。", + "warning": "警告:仅支持简单多边形,否则行为无法预测。" + }, + "otherGrinGlass": { + "title": "渐变折射率透光物", + "description": "折射率为自订函数 n(x,y) 的材料。" + }, + "Blocker": { + "title": "吸光片", + "description": "线段形状的吸光片,光线射到其上后就不会再射出。" + }, + "CircleBlocker": { + "title": "圆形遮光物", + "description": "圆形遮光物,光线射到其上后就不会再射出。" + }, + "Aperture": { + "title": "光圈", + "description": "一对线段形状的吸光片,可用对称方式调整其孔洞的大小。", + "instruction": "拖曳或点击两个端点以创建。" + }, + "DiffractionGrating": { + "title": "衍射光栅", + "description": "将光线依波长分割成不同角度的衍射光栅。", + "warning": "注意:衍射光的强度可能不准确。" + }, + "Ruler": { + "title": "直尺", + "description": "指定原点与另一点。" + }, + "Protractor": { + "title": "量角器", + "description": "指定圆心和圆周上一点作为零度位置。刻度单位为度。" + }, + "Detector": { + "title": "探测器", + "description": "测量通过一线段的能量流率(P)、垂直动量流率(F⊥)与水平动量流率(F∥)。单位为任意。" + }, + "TextLabel": { + "title": "文字", + "description": "文字标签。" + }, + "LineArrow": { + "title": "线段 / 箭头", + "description": "线段或箭头。" + }, + "Drawing": { + "title": "绘图", + "description": "手绘工具。", + "instruction": "拖曳以绘图。" + }, + "moveView": { + "title": "移动画面", + "description": "拖曳以移动视窗。(滑鼠右键拖曳也有相同的功能)" + }, + "modules": { + "import": "导入模块...", + "remove": "移除模块" + } + }, + "view": { + "title": "视图", + "rays": { + "title": "光线", + "description": "画出光线。当「光线密度」高时,光线呈现连续。" + }, + "extended": { + "title": "延长光线", + "description": "除光线实际路径外,亦画出其延长线。橘色、灰色分别表示向后、向前的延长线。", + "simulateColorsNote": "若使用「模拟色彩」,则改以光源颜色显示并以虚线区分。" + }, + "images": { + "title": "所有像", + "description": "点出像的位置。黄点表示实像,橘点表示虚像,灰点(图中没有)表示虚物。注意「光线密度」不够高时有些像无法正常显示。", + "simulateColorsNote": "若使用「模拟色彩」,则改以光源颜色显示并以点的大小区分。" + }, + "observer": { + "title": "观察者所见", + "description": "模拟从某位置见到的光线与像。蓝色圆形为观察者,与其相交的光线被其「观察」到。观察者无法知道光线真正的起始位置,但若其在某处相交,它会认为光线是从该处来的。光线以蓝色表示,相交处以黄色(实像)或橘色(虚像)表示。", + "simulateColorsNote": "若使用「模拟色彩」,则改以光源颜色显示。", + "instruction": "拖曳大蓝点以移动观察者。" + } + }, + "simulateColors": { + "title": "模拟色彩", + "description": "模拟光源的颜色(波长)、混色、遮光物与镜子的滤光,以及透光物的色散。", + "instruction": "选取物件后可调整这些参数。重叠多条不同波长的光线可用于模拟光谱。", + "warning": "屏幕显示之颜色仅为粗略近似,且当「光线密度」太高或太低时可能非常不准确。" + }, + "aboutPage": { + "description": "本项目,包括作品集内容,皆采用 [Apache License 2.0](/license) 授权条款,且官方版本位于 [PhyDemo(phydemo.app)](/phydemo)网站(原先于 ricktu288.github.io)。本项目源代码公开于[此 GitHub Repo](/github),欢迎您[贡献本项目](/contributing)。若有问题或建议,您可以在 GitHub 上建立 [Issue](/github/issues) 或 [Discussion](/github/discussions)(请使用英文),也可以传送电子邮件至 [ray-optics@phydemo.app](/email)(可使用中文)。", + "cite": "引用本项目", + "mainAuthors": "主要作者", + "contributors": "贡献者", + "contributorSorting": "GitHub 贡献者优先;其余依时间排序。", + "contributionCategories": { + "code": "代码", + "uiDesign": "介面设计", + "gallery": "作品集", + "module": "模块", + "translations": "{{languages}} 翻译" + } + }, + "languageDropdown": { + "title": "语言:{{language}}", + "translatedFraction": "已翻译 {{fraction}}" + } +} \ No newline at end of file diff --git a/locales/zh-CN/modules.json b/locales/zh-CN/modules.json new file mode 100644 index 00000000..3f788158 --- /dev/null +++ b/locales/zh-CN/modules.json @@ -0,0 +1,141 @@ +{ + "modulesPage": { + "description": { + "makeNewTools": "「模块」功能透过将本模拟器中现有的工具所建立的物件进行组合、特化或重新参数化,来制作新的工具。", + "appearAsTools": "导入的模块将显示为「其他」类别中的工具。请选择并依照控制点顺序点击空白处(参见「规格」)。", + "embeddedInScene": "导入的模块将嵌入于场景的数据中,所以当原作者更新时并不会自动更新。" + }, + "import": "导入", + "imported": "已导入", + "specification": { + "title": "规格", + "controlPointSequence": "控制点顺序", + "parameters": "参数" + }, + "customization": { + "title": "客制化", + "description": "您可直接在本网页程序中使用内置的JSON编辑器制作或客制化模块。请参见[教程](/modules/tutorial)。将导入的模块客制化仅会影响目前的场景。" + }, + "contribution": { + "title": "贡献", + "description": "欢迎您贡献项目至以上的清单。欲贡献您的模块,请参见[貢獻模块](/contributing/modules)。" + } + }, + "moduleData": { + "FresnelLens": { + "title": "菲涅耳透镜", + "description": "从半圆形透光物制成的菲涅耳透镜。[此作品集范例](/gallery/fresnel-lens)的模块化版本。", + "point1": "透镜的第一个端点", + "point2": "透镜的第二个端点", + "Nslice": "切片数量", + "refIndex": "透镜的折射率" + }, + "ContSpectrum": { + "title": "连续光谱光源", + "description": "具有均匀连续光谱的光源,以指定的步长离散化。只在「模拟色彩」模式中运作。", + "point1": "光线的起点", + "point2": "决定光线的方向", + "min": "波长最小值", + "step": "波长的步长", + "max": "波长最大值", + "brightness": "总亮度" + }, + "CircleSource": { + "title": "圆形光源", + "description": "将一系列均匀的180度点光源置于圆周上所形成的光源。", + "point1": "该圆形的圆心", + "r": "该圆形的半径", + "N": "点光源的数量", + "brightness": "总亮度" + }, + "Chaff": { + "title": "干扰箔", + "description": "矩形的干扰箔,由许多随机的镜子组成。[此作品集范例](/gallery/chaff-countermeasure)的模块化版本。", + "point1": "干扰箔的左上角", + "point2": "干扰箔的右下角", + "N": "干扰箔中镜子的数量", + "L": "镜子的长度" + }, + "BeamExpander": { + "title": "扩束镜", + "description": "两个理想透镜的组合,使得两者焦距之和等于两者间的距离。此组合可以扩大或缩小准直光束的直径[此作品集范例](/gallery/beam-expanders)的模块化版本。", + "point1": "第一个透镜的中心点", + "point2": "第二个透镜的第二个点", + "point3": "决定共同焦点的位置" + }, + "RayRelay": { + "title": "光线中继", + "description": "一系列相同的理想透镜,焦距为 \\(f\\),间距为 \\(d\\)。若且唯若\\(d\\leq 4f\\)时,可以保证光线轨迹不会发散。[此作品集范例](/gallery/ray-relaying)的模块化版本。", + "point1": "第一个透镜的第一个端点", + "point2": "第一个透镜的第二个端点(应与第一点有相同的 \\(x\\))", + "f": "透镜的焦距", + "d": "透镜之间的距离", + "N": "透镜的数量" + }, + "OpticalFiber": { + "title": "光纤", + "description": "指定核心和包层折射率的线状光纤。", + "point1": "光纤的第一个端点", + "point2": "光纤的第二个端点(应与第一个点有相同的 \\(y\\))", + "X": "核心的厚度", + "Y": "包层的厚度", + "n1": "核心的折射率", + "n2": "包层的折射率" + } + }, + "moduleTutorial": { + "title": "「射线光学模拟」模块制作教程", + "opening": { + "description": "本教程将引导您完成建立自定义模块的基本步骤。这个功能可完全在本模拟器网页程序中实现,而不需要其他的开发环境。", + "moduleIntroduction": "「线光学模拟」的「模块」功能允许将物件以模块化的方式组合在一起,其中可包含自定义参数、自定义控制点与物件数组。本功能透过将本模拟器中现有的工具所建立的物件进行组合、特化或重新参数化,来制作新的工具,以扩充本模拟器的功能。例如,`CircleSource`模块(请参见工具->其他->导入模块)将现有的「点光源(<360°)」工具所建立的一系列点光源沿着一个圆形组合在一起,成为一个「圆形光源」工具,这在模拟器中原本并不存在。`FresnelLens`模块则是将「透光物->自定义函数」工具特化,使函数表示菲涅耳透镜的特定曲线,由切片数参数化,以制作一个特化的「菲涅耳透镜」工具,这在模拟器中原本也不存在。除了制作新工具外,这个功能还可以使一些光学演示更具互动性。例如,通过拖曳`BeamExpander`模块的第三个控制点,可以直接观察两个透镜的共同焦点位置如何影响光束宽度,而无需分别调整两个透镜的焦距。", + "compareWithHandle": "注意并非所有的自定义控制点都需要模块。一些简单的情况可能可以通过「控制杆」功能实现(请参见模拟器右下角的帮助弹出窗口中的「群组、旋转和缩放物件」部分)。由于制作模块比建立控制杆复杂得多,您应该在考虑制作模块之前检查您的情况是否可以通过「控制杆」功能实现。比如[这个例子](/gallery/black-cat-becomes-white)展示了一个相对复杂但不必使用模块的自定义控制点(将两个塑料袋从水中移开)。" + }, + "jsonEditor": { + "title": "内置的JSON编辑器", + "currentlyNoVisual": "本应用目前没有用于建立模块的视觉界面,因此您需要直接编辑场景的JSON原始码。", + "enableJsonEditor": "您可以通过点击应用程序右上角的「设置」下拉菜单,然后勾选「显示JSON编辑器」来启用内置的JSON编辑器。原始码编辑器会出现在界面的左侧,并显示目前场景的JSON原始码。请确保您有足够大的屏幕,因为这个功能在行动装置上效果不佳。", + "updateAccordingly": "当您使用可视化场景编辑器修改场景时,JSON编辑器中的原始码将自动更新,且更改的部分会突出显示。反之,直接在JSON编辑器中编辑原始码将相应更新场景。如果您不熟悉JSON或任何基于文字的数据格式,您可能会希望花一些时间来熟悉它。", + "objsArray": "特别是,当您将一个物件新增到场景中时,它将被新增到`objs`数组中。如果您将某些属性修改为非预设值,它们将作为该物件的键值对出现。", + "inIframesBelow": "注意:如果您在本教程页面中看不到下面的iframe中的JSON编辑器,请启用它并重新加载本页,因为您需要查看原始码以了解它的运作方式。" + }, + "basics": { + "title": "模块的基本概念", + "lookAtExample": "让我们看第一个例子。", + "lookAtJson": "您会看到四段文字。通过查看JSON编辑器,您将看到前两段直接位于顶层的`objs`数组中,但后两段位于`modules.ExampleModule.objs`中。", + "moduleDef": "`module`是一个字典,其中键是模块的名称(在本例中是`ExampleModule`),值是该模块的定义。特别是,`modules.ExampleModule.objs`数组描述了该模块中的物件(模板),这与描述场景中的物件的顶层`objs`数组不同。", + "putToScene": "要将模块中的物件放到场景中,我们需要一个「模块物件」,它位于顶层`objs`数组中,本例中是`objs[2]`,其类型是`ModuleObj`,其`module`属性是模块的名称。", + "moduleDefNotEditable": "`modules`字典中的模块定义无法由可视化场景编辑器编辑。因此,当您点选本例中的后两段文字时,您只选择了模块物件,而不是模块中的物件。由于本例中模块定义中的文字坐标是绝对坐标,因此后两段文字无法被拖曳。我们将在后面学习到如何使用控制点来使它们可被拖曳。", + "demodulize": "当您提取模块物件时,物件栏上会有一个「取消模块化」按钮。点选后会将模块物件「展开」为构成此模块的物件,此时`objs`将包含所有四段文字。这个操作是不可逆的(除非点击「复原」)。", + "createModule": "目前建议制作模块的方式为,首先使用JSON编辑器建立一个空的模块,然后使用可视化场景编辑器新增一些物件,最后使用JSON编辑器将这些物件从`objs`剪下并粘贴到`modules.ModuleName.objs`中。" + }, + "parameters": { + "title": "新增参数", + "lookAtExample": "模块中的物件可以由一组参数来定义。让我们看一个简单的例子", + "paramsArray": "这里`modules.ModuleName.params`是一个由形如`\"名称=起始值:增量:终止值:预设值\"`的字串构成的数组,定义了变数的名称和数值滑杆的范围。当提取模块物件时,滑杆将出现在物件栏上。", + "equationSyntax": "在`modules.ExampleModule.objs`数组中,任何值都可以使用这些参数来表示。在字串中(例如`TextLabel`的`text`属性)中,带有参数的数学式被反引号包围。对于数值参数(例如`TextLabel`的`fontSize`属性),您需要将其改为字串,以便您可以在其中使用反引号格式。因此每条数学式都被一对反引号和一对引号包围。这些数学式将使用math.js来计算([语法](/mathjs/syntax))。请参见该网页以了解您可以在数学式中使用的语法和函数。", + "valueStorage": "参数的实际值位于模块物件的`params`属性中。这部分与模块定义不同,其可以通过滑杆直接由可视化场景编辑器编辑。" + }, + "controlPoints": { + "title": "新增控制点", + "lookAtExample": "为了使模块物件可被拖曳,我们需要使用一组控制点来对模块中的物件位置进行参数化。让我们看一个例子", + "coordinatesOfControlPoints": "这里`modules.ModuleName.numPoints`描述了控制点的数量。控制点坐标之符号为 (`x_1`, `y_1`)、(`x_2`, `y_2`) 等等。其用在`modules.ExampleModule.objs`中的方式与前一节所述之参数相同。请注意索引从1开始。", + "valueStorage": "控制点的实际值位于模块物件的`controlPoints`属性中,其可以直接由可视化场景编辑器编辑,而非如第一个例子中写死在模块定义中的坐标。每个控制点在场景中显示为两个同心的灰色圆形,并且可以被拖曳。若您拖曳模块物件的其他地方(如文字标签),则所有的控制点会一起移动。", + "createAsTool": "由于我们的模块物件已经可以移动,我们可以很容易地建立多个实例,就像在本模拟器中其他的工具中一样。模块的名称显示在工具->其他菜单中,您可以选择它,然后按两个点来指定两个控制点的位置,就可建立此模块的另一个实例。您也可以使用物件栏上的「复制」按钮。" + }, + "arrayAndConditional": { + "title": "数组与条件", + "lookAtExample": "使用数组和条件语法,可以建立更复杂的模块。让我们看一个例子", + "specialKeys": "在`modules.ExampleModule.objs`中,任何数组中的物件都可以有两个特殊的键:`\"for\"`和`\"if\"`。`\"for\"`键的值是一个描述循环变数的字串,格式为`\"名称=起始值:增量:终止值\"`,或者是一个包含多个这种格式的字串的数组,描述多维循环。这样的物件在数组中根据循环变数被复制多次。`\"if\"`键的值是则是一个表示布尔值的字串,使得该物件只在布尔值为真时才会包含在数组中。", + "preventInfiniteLoop": "为了防止意外的无穷循环,每个`\"for\"`循环的总迭代次数由模块定义中的`maxLoopLength`属性限制,其预设值为1000。如果需要,您可以将此属性设定为更大的值。" + }, + "objsWithEqn": { + "title": "内置自定义数学式功能的物件", + "description": "对于已经具有自定义数学式输入的物件(例如镜子->自定义函数),JSON中的数学式属性是一个表示LaTeX数学式的字串,而不是math.js表达式。要在数学式中包含自定义参数,您必须将LaTeX数学式视为普通字串,并使用普通字串的模板语法。因此,反引号括起来的部分是math.js表达式,而反引号外部的则是LaTeX数学式。模块参数只能在math.js的部分中使用,而物件内置的自定义函数的自变量(例如\\(x\\))只能在LaTeX的部分中使用。以下例子产生一个形状为\\(y=\\cos(2\\pi x+\\phi)\\)的镜子,其中\\(\\phi\\)为模块参数", + "future": "未来可能会有一种统一的方式来输入数学式。" + }, + "objsWithShapeParam": { + "title": "内置形状参数化功能的物件", + "description": "对于已经支持使用不同方式定义其形状的物件(目前仅有透光物->球面透镜),有特殊的JSON语法可用于在模块定义中用这些方式来定义该物件,即使在顶层`objs`数组中这类的物件总是以形状来定义。以下是一个例子" + } + } +} \ No newline at end of file diff --git a/locales/zh-CN/simulator.json b/locales/zh-CN/simulator.json new file mode 100644 index 00000000..095972ca --- /dev/null +++ b/locales/zh-CN/simulator.json @@ -0,0 +1,335 @@ +{ + "welcome": { + "title": "欢迎使用“射线光学模拟”", + "instruction": "若要加入光学元件,请选择工具并点击空白处。\n若要载入示例,[请前往“作品集”页面](/gallery)。", + "loading": "正在从网址载入场景... 请稍候。" + }, + "common": { + "saveButton": "保存", + "cancelButton": "取消", + "defaultOption": "默认", + "closeButton": "关闭" + }, + "file": { + "title": "文件", + "undo": { + "title": "撤销" + }, + "redo": { + "title": "重做" + }, + "reset": { + "title": "清空" + }, + "save": { + "title": "保存" + }, + "open": { + "title": "打开", + "description": "打开文件或背景图片。背景图片将从坐标原点显示。(或拖放文件)" + }, + "export": { + "title": "导出为PNG/SVG" + }, + "copyLink": { + "title": "复制分享连结", + "description": "复制并前往本场景的专属网址,以便分享连结(可考虑透过短网址工具)。另见设定->自动同步网址。" + }, + "viewGallery": { + "title": "浏览作品集", + "description": "前往「作品集」页面以载入示例。" + } + }, + "settings": { + "title": "设定", + "more": "更多选项", + "rayDensity": { + "title": "光线密度", + "description": "决定从光束与点光源射出的光线数量。这也会影响到像的侦测与颜色渲染的准确性。" + }, + "layoutAids": { + "title": "排版辅助", + "showGrid": "网格", + "snapToGrid": "对齐网格", + "lockObjs": "锁定物件" + }, + "gridSize": { + "title": "网格大小" + }, + "observerSize": { + "title": "观察者大小" + }, + "lengthScale": { + "title": "长度尺度", + "description": "如果将默认的长度单位视为常见的物理单位(例如毫米)时,模拟的物理系统看起来太小或太大,则可以使用此比例来缩放场景中的外观(例如线宽)。" + }, + "zoom": { + "title": "缩放" + }, + "language": { + "title": "语言" + }, + "autoSyncUrl": { + "title": "自动同步网址", + "description": "启用时,网址会随着场景自动更新,而不必持续手动储存场景。如需设定标题,请用文件->保存->重命名。" + }, + "showJsonEditor": { + "title": "显示 JSON 编辑器", + "description": "显示表达场景代码的 JSON 编辑器。在创建自定义模块时需要使用(见工具->其他->导入模块->创建自定义模块)。" + }, + "showStatusBox": { + "title": "显示状态方块", + "description": "显示状态方块,其中包含滑鼠座标,效能信息,以及被截断的亮度(光线在内反射的无穷级数中被截断的总亮度)。" + }, + "showHelpPopups": { + "title": "显示提示泡泡", + "description": "决定滑鼠移到按钮上方时是否显示提示泡泡(须重新载入网页以套用变更)" + }, + "advancedHelp": "进阶说明详见右下角的说明图示。" + }, + "objBar": { + "showAdvanced": { + "title": "更多选项…" + }, + "applyToAll": { + "title": "套用全部" + }, + "duplicate": { + "title": "复制" + }, + "delete": { + "title": "删除" + }, + "unselect": { + "title": "取消选取", + "description": "取消选取此物件(在空白处按滑鼠右键也有相同的功能)" + } + }, + "sceneObjs": { + "common": { + "lengthUnitInfo": "本模拟器中的长度单位(除波长外)为一个任意单位。您可将其视为任何物理单位(例如毫米),只要在整个模拟中保持一致。如果单位看起来太小或太大,请调整设定->长度尺度。", + "brightness": "亮度", + "brightnessInfo": { + "rayDensity": "只在「光线密度」够高时才有作用。", + "rayDensitySlider": "如需改变射出的光线数量,请调整全域性的「光线密度」滑杆。" + }, + "wavelength": "波长", + "emisAngle": "发射角", + "random": "随机", + "lambert": "朗伯", + "focalLength": "焦距", + "eqnInfo": { + "constants": "支持的常数", + "operators": "支持的运算符", + "functions": "支持的函数" + }, + "imageDetectionWarning": "本工具不支持像的侦测。", + "nonSimulateColorsWarning": "本工具只在「模拟色彩」模式下运作。" + }, + "Beam": { + "imageDetectionWarning": "使用发散或随机光束时,像的侦测可能无法正常运作。" + }, + "AngleSource": { + "symmetric": "对称" + }, + "BaseFilter": { + "filter": "滤光", + "bandwidth": "带宽", + "invert": "反向" + }, + "IdealMirror": { + "cartesianSign": "笛卡尔符号约定" + }, + "BeamSplitter": { + "transRatio": "透光率" + }, + "BaseGlass": { + "refIndex": "折射率", + "refIndexInfo": { + "relative": "于另一透光物内部时为相对值", + "effective": "如需模拟此物件之(绝对)折射率为 n₁,但其位于折射率为 n₀ 之另一透光物内部的情形,则此处折射率应设为 n₁/n₀ 。在更复杂的组合中,若多个透光物互相重叠,则重叠区域之等效折射率为个别折射率之乘积。" + }, + "cauchyCoeff": "柯西系数" + }, + "SphericalLens": { + "defBy": { + "radiiOfCurvature": "曲率半径", + "focalDistances": "前/后焦距" + } + }, + "BaseGrinGlass": { + "refIndexFnInfo": { + "constants": "支持的常数", + "operators": "支持的运算符", + "functions": "支持的函数", + "lambda": "如需模拟色散,请用参数 {{lambda}} 代表真空中波长,单位为纳米。", + "diff": "仅支持可微函数。", + "origin": "n(x,y)的原点为绝对座标,不跟随对象移动。在控制点上点两下可显示其绝对座标。", + "accuracy": "如需较精确的模拟,请见「更多选项...」" + }, + "refIndexFnOrigin": "n(x,y)的原点", + "stepSize": "数值求解器步长", + "stepSizeInfo": "用欧拉法求解光线程函方程(eikonal ray equation)的步长 - 更多资讯详见 'BaseGrinGlass.js' 中的 'step' 函数与原始码文件。", + "intersectTol": "相交容忍度", + "symbolicBodyMerging": "符号式物体融合", + "symbolicBodyMergingInfo": { + "all": "本选项会套用至所有渐变折射率透光物。", + "impl": "本模拟器目前有两种光线经过不同渐变折射率介质的实作 - 数值与符号(见 'BaseGrinGlass.js' 中的 'multRefIndex' 与 'devRefIndex' 函数)。", + "implNote": "数值的实作较快,但使用多个渐变折射率介质,且至少有一个介质的折射率没有在整个平面上有定义时,无法在所有情况下正常运作(取决于具体情况)。相较之下,符号的实作较慢但在这种情况下仍可正常运作。" + } + }, + "CircleGrinGlass": { + "epsInfo": { + "units": "单位 - [长度]^2.", + "functions": "本数值容忍度被用于 'CircleGrinGlass.js' 中的 'isOutsideGlass', 'isInsideGlass' 以及 'isOnBoundary' 函数。" + } + }, + "GrinGlass": { + "epsInfo": { + "units": "单位 - [长度].", + "functions": "本数值容忍度被用于 'GrinGlass.js' 中的 'isOutsideGlass', 'isInsideGlass' 以及 'isOnBoundary' 函数。" + } + }, + "Aperature": { + "diameter": "直径" + }, + "DiffractionGrating": { + "lineDensity": "线数/{{lengthUnit}}", + "customBrightness": "自定义亮度", + "customBrightnessInfo": "启用时,衍射光的亮度将由一数值数组来决定,对应到 m = 0, 1, -1, 2, -2, ...。这些数字为相对于入射光的亮度。数组中没有的数值将被设为0。例如,\"1, 0.5, 0.5\" 表示 m=0 的光线与入射光的亮度相同,m=1 与 m=-1 的光线为入射光的一半,其他光线则被忽略。", + "slitRatio": "狭缝宽度 / 线间距", + "mirrored": "反射" + }, + "Ruler": { + "scaleInterval": "刻度间距" + }, + "Detector": { + "info": { + "P": "P: 能量流率(通量),单位为 B/s(见下文)。", + "Fperp": "F⊥: 垂直动量流率,单位为 (B/s)/c。", + "Fpar": "F∥: 平行动量流率,单位为 (B/s)/c。", + "irradiance": "导出的 CSV 中的辐照度单位为 (B/s)/L。", + "length": "L 是本模拟器中使用的任意长度单位。", + "B": "B 是辐射通量或光通量的任意单位,对应到「亮度」选项的单位:非朗伯光束为 B/L,点光源为 500B/360°。", + "s": "无量纲因子 s 是「设定」->「显示状态栏」中显示的「亮度尺度」,当「光线密度」高于某个阈值时为1,否则与「光线密度」成正比。", + "truncation": "如果某些光线在内反射的无穷级数中被截断,则总截断量将显示为误差估计。" + }, + "irradMap": "辐照度图", + "binSize": "组距", + "exportData": "导出数据" + }, + "TextLabel": { + "textHere": "在此输入文字", + "fontSize": "字型大小", + "font": "字型", + "fontStyle": "样式", + "fontStyles": { + "normal": "正常", + "bold": "粗体", + "italic": "斜体", + "boldItalic": "粗斜体", + "oblique": "倾斜", + "boldOblique": "粗倾斜" + }, + "alignment": "对齐", + "alignments": { + "left": "左", + "center": "中", + "right": "右" + }, + "smallCaps": "小型大写", + "angle": "角度" + }, + "LineArrow": { + "arrow": "前向箭头", + "backArrow": "后向箭头" + }, + "Drawing": { + "finishDrawing": "停止绘图" + }, + "ModuleObj": { + "module": "模块", + "demodulize": "取消模块化" + }, + "Handle": { + "handle": "控制杆", + "transformation": "变换", + "transformations": { + "translation": "平移", + "xTranslation": "X 平移", + "yTranslation": "Y 平移", + "rotation": "旋转", + "scaling": "缩放" + } + }, + "CropBox": { + "title": "导出", + "cropBoxSize": "剪取框大小", + "format": "格式", + "width": "宽度", + "rayCountLimit": "光线数量上限", + "svgWarning": "导出为SVG:不支持混色与相对折射率低于1的情形。", + "rayCountWarning": "目前场景中的光线数量大于光线数量上限。 您可能需要将剪取框选项中的光线数量上限调高。" + } + }, + "saveModal": { + "title": "保存", + "description": { + "autoSync": "您可使用设定->自动同步网址而不必存成文件。", + "rename": "按「重命名」会改变标题但不会存成文件。", + "contribute": "您可以考虑[贡献新的项目](/contributing/gallery)到[「作品集」](/gallery)中。" + }, + "fileName": "名称", + "rename": "重命名" + }, + "moduleModal": { + "title": "导入模块", + "makeCustomModules": "制作自定义模块", + "conflict": "场景中已有一个同名但不相同的模块。您可以指定新的名称,或保留相同名称以取代原模块。" + }, + "languageModal": { + "title": "语言", + "translatedFraction": "已翻译", + "helpTranslate": "协助我们翻译本程序" + }, + "generalWarnings": { + "shareLinkTooLong": "本网址过长,在部分平台上可能无法正常运作。建议改用「保存」并分享文件。", + "autoSyncUrlTooLarge": "本场景过大,无法与网址同步。 请自行储存场景。", + "identicalObjects": "场景中有两个完全相同的光学元件完全重合。 这可能会导致非预期的行为。", + "brightnessInconsistent": "有至少两个光源的亮度以不一致的比例达到饱和。这可能会导致探测器的读数与色彩渲染错误。请提高光线密度或降低光源亮度。" + }, + "statusBox": { + "rayCount": "光线片段数量", + "totalTruncation": "被截断的亮度", + "brightnessScale": "亮度尺度", + "timeElapsed": "花费时间", + "forceStopped": "已强制终止。", + "mouseCoordinates": "滑鼠座标" + }, + "footer": { + "processing": "处理中…… 按此处以终止。", + "helpPopup": { + "constrainedDragging": { + "title": "限制拖曳行为", + "description": "拖曳物件时,按住 Shift 可限制于水平或垂直移动;按住 Ctrl 可复制物件。建立线型物件或拖曳其端点时,按住 Shift 可锁定角度或吸附至 0°、45°、90°;按住 Ctrl 可对于中心点旋转或缩放。" + }, + "groupRotateScale": { + "title": "群组、旋转及缩放物件", + "description": "按住 Ctrl,点击多个控制点(如端点),并点击空白处可将这些点群组并建立控制杆。拖曳控制杆(或按方向键)可平移群组;Shift+拖曳可限制于水平或垂直移动;Ctrl+拖曳可旋转群组;Ctrl+Shift+拖曳可缩放群组。可移动「+」设定旋转或缩放中心。点击控制杆并按 Ctrl+D 可复制群组;按 Delete 可解散群组。" + }, + "editCoordinates": { + "title": "直接编辑座标", + "description": "对控制点(如端点)点两下或按右键,输入 (x,y) 座标,然后按 Enter。" + }, + "keyboardShortcuts": { + "title": "键盘快速键", + "description": "当一物件在被选取的状态(被点击)时,按方向键可移动物件;按 Ctrl+D 可复制物件;按 Delete 可删除物件。" + }, + "contactUs": { + "title": "联络我们", + "description": "建议使用 GitHub 上的 [Discussions](/github/discussions) 或 [Issues](/github/issues) 功能(请使用英文)。若您对 GitHub 不熟,也可发送电子邮件至 [ray-optics@phydemo.app](/email)(可使用中文)。", + "contribute": "也欢迎直接进行贡献(见[贡献指南](/contributing))。" + } + } + } +} \ No newline at end of file diff --git a/locales/zh-TW.json b/locales/zh-TW.json deleted file mode 100644 index aaef178d..00000000 --- a/locales/zh-TW.json +++ /dev/null @@ -1,863 +0,0 @@ -{ - "appName": { - "message": "模擬器 - 線光學模擬" - }, - "appShortName": { - "message": "線光學" - }, - "appDesc": { - "message": "自由、開源的網頁程式,用於建立及模擬平面幾何光學場景。" - }, - "homepage_desc": { - "message": "建立平面幾何光學場景,並即時模擬光線行為。
完全免費,免下載,原始碼公開於 GitHub。" - }, - "launch_simulator": { - "message": "啟動程式" - }, - "home": { - "message": "首頁" - }, - "home_url": { - "message": "https://phydemo.app/ray-optics/tw/" - }, - "gallery": { - "message": "作品集" - }, - "gallery_url": { - "message": "https://phydemo.app/ray-optics/tw/gallery/" - }, - "welcome": { - "message": "歡迎使用「線光學模擬」
若要加入光學元件,請選擇工具並點擊空白處。
若要載入範例,請前往「作品集」頁面。" - }, - "loading_msg": { - "message": "歡迎使用「線光學模擬」
正在從網址載入場景... 請稍候。" - }, - "toolbar_title": { - "message": "工具:" - }, - "toolname_SingleRay": { - "message": "單一光線" - }, - "toolname_AngleSource": { - "message": "點光源" - }, - "toolname_PointSource": { - "message": "點光源" - }, - "toolname_Beam": { - "message": "光束" - }, - "toolname_mirror_": { - "message": "鏡子" - }, - "toolname_Mirror": { - "message": "鏡子" - }, - "toolname_ArcMirror": { - "message": "鏡子" - }, - "toolname_ParabolicMirror": { - "message": "鏡子" - }, - "toolname_CustomMirror": { - "message": "鏡子" - }, - "toolname_IdealMirror": { - "message": "理想曲面鏡" - }, - "toolname_glass_": { - "message": "透光物" - }, - "toolname_blocker_": { - "message": "遮光物" - }, - "toolname_BeamSplitter": { - "message": "分光鏡" - }, - "toolname_PlaneGlass": { - "message": "透光物" - }, - "toolname_CircleGlass": { - "message": "透光物" - }, - "toolname_CircleGrinGlass": { - "message": "漸變折射率透光物" - }, - "toolname_Glass": { - "message": "透光物" - }, - "toolname_GrinGlass": { - "message": "漸變折射率透光物" - }, - "toolname_IdealLens": { - "message": "理想透鏡" - }, - "toolname_SphericalLens": { - "message": "球面透鏡" - }, - "toolname_CustomGlass": { - "message": "透光物" - }, - "toolname_Blocker": { - "message": "吸光片" - }, - "toolname_Aperture": { - "message": "光圈" - }, - "toolname_CircleBlocker": { - "message": "圓形遮光物" - }, - "toolname_DiffractionGrating": { - "message": "繞射光柵Beta" - }, - "toolname_Ruler": { - "message": "直尺" - }, - "toolname_Protractor": { - "message": "量角器" - }, - "tool_Detector": { - "message": "探測器" - }, - "toolname_Detector": { - "message": "探測器" - }, - "toolname_TextLabel": { - "message": "文字" - }, - "toolname_LineArrow": { - "message": "線段" - }, - "toolname_Drawing": { - "message": "繪圖" - }, - "toolname_Handle": { - "message": "控制桿" - }, - "toolname_CropBox": { - "message": "匯出" - }, - "toolname_ModuleObj": { - "message": "模組Beta" - }, - "tool_more_": { - "message": "其他" - }, - "toolname_": { - "message": "移動畫面" - }, - "modebar_title": { - "message": "檢視:" - }, - "modename_light": { - "message": "光線" - }, - "modename_extended_light": { - "message": "延長光線" - }, - "modename_images": { - "message": "所有像" - }, - "modename_observer": { - "message": "觀察者所見" - }, - "simulateColors": { - "message": "模擬色彩" - }, - "File: ": { - "message": "檔案" - }, - "Tools: ": { - "message": "工具" - }, - "tool_SingleRay": { - "message": "單一光線" - }, - "tool_Beam": { - "message": "光束" - }, - "tool_PointSource": { - "message": "點光源 (360°)" - }, - "tool_AngleSource": { - "message": "點光源 (<360°)" - }, - "tool_PointSource_": { - "message": "點光源" - }, - "tool_lightSource_": { - "message": "光源" - }, - "tool_mirror_": { - "message": "鏡子" - }, - "tool_Mirror": { - "message": "線段" - }, - "tool_ArcMirror": { - "message": "圓弧" - }, - "tool_ParabolicMirror": { - "message": "拋物線" - }, - "tool_CustomMirror": { - "message": "自訂函數" - }, - "tool_BeamSplitter": { - "message": "分光鏡" - }, - "tool_IdealMirror": { - "message": "理想曲面鏡" - }, - "tool_glass_": { - "message": "透光物" - }, - "tool_blocker_": { - "message": "遮光物" - }, - "tool_PlaneGlass": { - "message": "半平面" - }, - "tool_CircleGlass": { - "message": "圓形" - }, - "tool_CircleGrinGlass": { - "message": "漸變折射率圓形" - }, - "tool_Glass": { - "message": "多邊形 / 圓弧" - }, - "tool_GrinGlass": { - "message": "漸變折射率多邊形" - }, - "tool_IdealLens": { - "message": "理想透鏡" - }, - "tool_SphericalLens": { - "message": "球面透鏡" - }, - "tool_CustomGlass": { - "message": "自訂函數" - }, - "tool_Blocker": { - "message": "吸光片" - }, - "tool_Aperture": { - "message": "光圈" - }, - "tool_CircleBlocker": { - "message": "圓形遮光物" - }, - "tool_DiffractionGrating": { - "message": "繞射光柵Beta" - }, - "tool_Ruler": { - "message": "直尺" - }, - "tool_Protractor": { - "message": "量角器" - }, - "tool_TextLabel": { - "message": "文字" - }, - "tool_LineArrow": { - "message": "線段 / 箭頭" - }, - "tool_Drawing": { - "message": "繪圖" - }, - "tool_": { - "message": "移動畫面" - }, - "View: ": { - "message": "檢視" - }, - "Settings: ": { - "message": "設定" - }, - "moresettings": { - "message": "更多選項" - }, - "mode_rays": { - "message": "光線" - }, - "mode_extended": { - "message": "延長光線" - }, - "mode_images": { - "message": "所有像" - }, - "mode_observer": { - "message": "觀察者所見" - }, - "zoom": { - "message": "縮放" - }, - "help": { - "message": "幫助" - }, - "rayDensity": { - "message": "光線密度" - }, - "raydensity": { - "message": "光線密度:" - }, - "undo": { - "message": "復原" - }, - "redo": { - "message": "重做" - }, - "reset": { - "message": "重設" - }, - "save": { - "message": "儲存" - }, - "rename": { - "message": "重新命名" - }, - "get_link": { - "message": "複製分享連結" - }, - "export_svg": { - "message": "匯出為PNG/SVG" - }, - "view_gallery": { - "message": "瀏覽作品集" - }, - "save_name": { - "message": "名稱" - }, - "save_cancel": { - "message": "取消" - }, - "save_description": { - "message": "
  • 您可使用設定->自動同步網址而不必存成檔案。
  • 按「重新命名」會改變標題但不會存成檔案。
  • 您可以考慮貢獻新的項目「作品集」中。
" - }, - "open": { - "message": "開啟" - }, - "layoutaids": { - "message": "排版輔助" - }, - "lockObjs": { - "message": "鎖定物件" - }, - "showGrid": { - "message": "格線" - }, - "snapToGrid": { - "message": "對齊格線" - }, - "snaptogrid": { - "message": "對齊格線" - }, - "length_unit_popover": { - "message": "本模擬器中的長度單位(除波長外)為一個任意單位。您可將其視為任何物理單位(例如毫米),只要在整個模擬中保持一致。如果單位看起來太小或太大,請調整設定->長度尺度。" - }, - "lengthScale": { - "message": "長度尺度Beta" - }, - "lengthScale_popover": { - "message": "如果將預設的長度單位視為常見的物理單位(例如毫米)時,模擬的物理系統看起來太小或太大,則可以使用此比例來縮放場景中的外觀(例如線寬)。" - }, - "brightness": { - "message": "亮度" - }, - "wavelength": { - "message": "波長 (nm)" - }, - "dichroic": { - "message": "二色性" - }, - "filter": { - "message": "濾光" - }, - "bandwidth": { - "message": "帶寬 (nm)" - }, - "invert": { - "message": "反向" - }, - "emisAngle": { - "message": "發射角 (°)" - }, - "mirrored": { - "message": "反射" - }, - "lineDensity": { - "message": "線數/mm" - }, - "slitRatio": { - "message": "狹縫寬度 / 線間距" - }, - "customBrightness": { - "message": "自訂亮度" - }, - "customBrightness_note_popover": { - "message": "啟用時,繞射光的亮度將由一數值陣列來決定,對應到 m = 0, 1, -1, 2, -2, ...。這些數字為相對於入射光的亮度。陣列中沒有的數值將被設為 0。例如,\"1, 0.5, 0.5\" 表示 m=0 的光線與入射光的亮度相同,m=1 與 m=-1 的光線為入射光的一半,其他光線則被忽略。" - }, - "symmetric": { - "message": "對稱" - }, - "eqn_note": { - "message": "
  • 支援的常數:
    pi e
  • 支援的運算子:
    + - * / ^
  • 支援的函數:
    sqrt sin cos tan sec csc cot sinh cosh tanh log exp arcsin arccos arctan arcsinh arccosh arctanh floor round ceil trunc sgn max min abs
" - }, - "symbolic_grin": { - "message": "符號式物體融合" - }, - "grin_refractive_index": { - "message": "
  • 支援的常數:
    pi e
  • 支援的運算子:
    + - * / ^
  • 支援的函數:
    sqrt sin cos tan sec csc cot sinh cosh tanh log arcsin arccos arctan
  • 如需模擬色散,請用參數 lambda 代表真空中波長,單位為奈米。Beta
  • 僅支援可微函數。
  • n(x,y)的原點為絕對座標,不跟隨物件移動。在控制點上點兩下可顯示其絕對座標。
  • 如需較精確的模擬,請見「更多選項...」
" - }, - "symbolic_grin_note_popover": { - "message": "

本選項會套用至所有漸變折射率透光物。

本模擬器目前有兩種光線經過不同漸變折射率介質的實作 - 數值與符號(見 'CircleGrinGlass.js' 中的 'multRefIndex' 與 'devRefIndex' 函數)。

數值的實作較快,但使用多個漸變折射率介質,且至少有一個介質的折射率沒有在整個平面上有定義時,無法在所有情況下正常運作(取決於具體情況)。相較之下,符號的實作較慢但在這種情況下仍可正常運作。

" - }, - "focalLength": { - "message": "焦距" - }, - "cartesianSign": { - "message": "卡氏符號約定" - }, - "refIndex": { - "message": "折射率*" - }, - "radii_of_curvature": { - "message": "曲率半徑" - }, - "focal_distances": { - "message": "前/後焦距" - }, - "refIndex_origin": { - "message": "n(x,y)的原點" - }, - "stepSize": { - "message": "數值求解器步長" - }, - "intersectTol": { - "message": "相交容忍度" - }, - "random": { - "message": "隨機" - }, - "lambert": { - "message": "朗伯" - }, - "diameter": { - "message": "直徑" - }, - "irradMap": { - "message": "輻照度圖" - }, - "binSize": { - "message": "組距" - }, - "scaleInterval": { - "message": "刻度間距" - }, - "exportData": { - "message": "匯出數據" - }, - "demodulize": { - "message": "取消模組化" - }, - "fontSize": { - "message": "字型大小" - }, - "font": { - "message": "字型" - }, - "fontStyle": { - "message": "樣式" - }, - "normal": { - "message": "正常" - }, - "bold": { - "message": "粗體" - }, - "italic": { - "message": "斜體" - }, - "bolditalic": { - "message": "粗斜體" - }, - "oblique": { - "message": "傾斜" - }, - "boldoblique": { - "message": "粗傾斜" - }, - "alignment": { - "message": "對齊" - }, - "left": { - "message": "左" - }, - "center": { - "message": "中" - }, - "right": { - "message": "右" - }, - "text_here": { - "message": "在此輸入文字" - }, - "smallCaps": { - "message": "小型大寫" - }, - "angle": { - "message": "角度 (°)" - }, - "arrow": { - "message": "前向箭頭" - }, - "backArrow": { - "message": "後向箭頭" - }, - "stop_drawing": { - "message": "停止繪圖" - }, - "cropBoxSize": { - "message": "剪取框大小" - }, - "format": { - "message": "格式" - }, - "width": { - "message": "寬度" - }, - "rayCountLimit": { - "message": "光線數量上限" - }, - "transformation": { - "message": "變換Beta" - }, - "default": { - "message": "預設" - }, - "translation": { - "message": "平移" - }, - "xTranslation": { - "message": "X 平移" - }, - "yTranslation": { - "message": "Y 平移" - }, - "rotation": { - "message": "旋轉" - }, - "scaling": { - "message": "縮放" - }, - "beam_warning": { - "message": "使用發散或隨機光束時,像的偵測可能無法正常運作。" - }, - "image_detection_warning": { - "message": "本工具不支援像的偵測。" - }, - "non_simulateColors_warning": { - "message": "本工具只在「模擬色彩」模式下運作。" - }, - "brightness_note_popover": { - "message": "

只在「光線密度」夠高時才有作用。

如需改變射出的光線數量,請調整全域性的「光線密度」滑桿。

" - }, - "refIndex_note_popover": { - "message": "

*於另一透光物內部時為相對值

如需模擬此物件之(絕對)折射率為 n₁,但其位於折射率為 n₀ 之另一透光物內部的情形,則此處折射率應設為 n₁/n₀ 。在更複雜的組合中,若多個透光物互相重疊,則重疊區域之等效折射率為個別折射率之乘積。

" - }, - "stepSize_note_popover": { - "message": "

用歐拉法求解光線程函方程(eikonal ray equation)的步長 - 更多資訊詳見 'CircleGrinGlass.js' 中的 'step' 函數與原始碼文件。

" - }, - "eps_CircleGrinGlass_note_popover": { - "message": "

單位 - [長度]^2.

本數值容忍度被用於 'CircleGrinGlass.js' 中的 'isOutsideGlass', 'isInsideGlass' 以及 'isOnBoundary' 函數。

" - }, - "eps_GrinGlass_note_popover": { - "message": "

單位 - [長度].

本數值容忍度被用於 'GrinGlass.js' 中的 'isOutsideGlass', 'isInsideGlass' 以及 'isOnBoundary' 函數。

" - }, - "cauchyCoeff": { - "message": "柯西係數" - }, - "transRatio": { - "message": "透光率" - }, - "applytoall": { - "message": "套用全部" - }, - "duplicate": { - "message": "複製" - }, - "delete": { - "message": "刪除" - }, - "unselect": { - "message": "取消選取" - }, - "unselect_popover": { - "message": "取消選取此物件(在空白處按滑鼠右鍵也有相同的功能)" - }, - "showadvanced": { - "message": "更多選項…" - }, - "processing": { - "message": "處理中…… 按此處以終止。" - }, - "contribute": { - "message": "貢獻" - }, - "github": { - "message": "GitHub" - }, - "about": { - "message": "關於" - }, - "about_url": { - "message": "https://phydemo.app/ray-optics/tw/about" - }, - "translate": { - "message": "協助我們翻譯本程式" - }, - "translated": { - "message": "已翻譯" - }, - "undo_popover": { - "message": "復原上個動作。(Ctrl+Z)" - }, - "redo_popover": { - "message": "重做上個動作。(Ctrl+Y)" - }, - "reset_popover": { - "message": "清空整個場景。" - }, - "save_popover": { - "message": "將目前場景存檔。" - }, - "open_popover": { - "message": "開啟檔案或背景圖片。背景圖片將從座標原點顯示。(或拖放檔案)" - }, - "get_link_popover": { - "message": "複製並前往本場景的專屬網址,以便分享連結(可考慮透過短網址工具)。另見設定->自動同步網址。" - }, - "get_link_warning": { - "message": "本網址過長,在部分平臺上可能無法正常運作。建議改用「儲存」並分享檔案。" - }, - "export_svg_warning": { - "message": "匯出為SVG:不支援混色與相對折射率低於1的情形。" - }, - "export_ray_count_warning": { - "message": "目前場景中的光線數量大於光線數量上限。您可能需要將剪取框選項中的光線數量上限調高。" - }, - "view_gallery_popover": { - "message": "前往「作品集」頁面以載入範例。" - }, - "tool_SingleRay_popover": { - "message": "由兩點決定一條光線。(拖曳或點擊以創建. 第一個點是光源,射向第二個點。)" - }, - "tool_Beam_popover": { - "message": "由一線段產生平行或發散光束,密度由「光線密度」滑桿決定。(拖曳或點擊以創建。)" - }, - "tool_PointSource_popover": { - "message": "由一點向四周發射光線,數量由「光線密度」滑桿決定。(點擊以創建。)" - }, - "tool_AngleSource_popover": { - "message": "指定發射角之點光源。" - }, - "tool_Mirror_popover": { - "message": "模擬光線射到鏡子時的反射。(拖曳或點擊以創建。)" - }, - "tool_ArcMirror_popover": { - "message": "圓弧形的鏡子,由三點決定。(拖曳或點擊以創建。前兩個點定義弧形兩邊間的空隙,第三點決定弧的大小。)" - }, - "tool_ParabolicMirror_popover": { - "message": "拋物線形的鏡子,由三點決定。(拖曳或點擊以創建。)" - }, - "tool_CustomMirror_popover": { - "message": "形狀為自訂等式 y = f(x) 的鏡子,其中 (x,y) 為變換過的座標,使得兩控制點為 (-1,0) 及 (1,0)。 (拖曳或點擊以創建。)" - }, - "tool_BeamSplitter_popover": { - "message": "能穿透一個比例的光的鏡子。(拖曳或點擊以創建。)" - }, - "tool_IdealMirror_popover": { - "message": "完全符合面鏡公式(1/p + 1/q = 1/f)的理想化「曲面」鏡,可直接設定其焦距。(拖曳或點擊以創建。)" - }, - "tool_PlaneGlass_popover": { - "message": "模擬光線經過透光物體界面時的反射與折射。(拖曳或點擊以創建。)" - }, - "tool_CircleGlass_popover": { - "message": "圓形透光物,由圓心與表面上一點決定。(拖曳或點擊以創建。)" - }, - "tool_CircleGrinGlass_popover": { - "message": "折射率為自訂函數 n(x,y),邊界為圓形的透光物。(拖曳或點擊以創建。)" - }, - "tool_Glass_popover": { - "message": "任何由線段與圓弧組成的透光物。(點擊以建立線段,拖曳以建立弧形,點擊一開始的點以結束繪製。)" - }, - "tool_GrinGlass_popover": { - "message": "折射率為自訂函數 n(x,y),邊界為多邊形的透光物。警告:僅支援簡單多邊形,否則行為無法預測。(點擊以建立線段,點擊一開始的點以結束繪製。)" - }, - "tool_IdealLens_popover": { - "message": "完全符合薄透鏡公式(1/p + 1/q = 1/f)的理想化透鏡,可直接設定其焦距。(曳或點擊以創建。)" - }, - "tool_SphericalLens_popover": { - "message": "球面透鏡。(點擊以創建。)" - }, - "tool_CustomGlass_popover": { - "message": "形狀為自訂不等式 f(x) < y < g(x) 的透光物,其中 (x,y) 為變換過的座標,使得兩控制點為 (-1,0) 及 (1,0)。 (拖曳或點擊以創建。)" - }, - "tool_Blocker_popover": { - "message": "線段形狀的吸光片,光線射到其上後就不會再射出。(拖曳或點擊以創建。)" - }, - "tool_Aperture_popover": { - "message": "一對線段形狀的吸光片,可用對稱方式調整其孔洞的大小。(拖曳或點擊兩個端點以創建。)" - }, - "tool_CircleBlocker_popover": { - "message": "圓形遮光物,光線射到其上後就不會再射出。(拖曳或點擊以創建。)" - }, - "tool_DiffractionGrating_popover": { - "message": "將光線依波長分割成不同角度的繞射光柵。注意:繞射光的強度可能不準確。(拖曳或點擊以創建。)" - }, - "tool_Ruler_popover": { - "message": "指定原點與另一點。(拖曳或點擊以創建。)" - }, - "tool_Protractor_popover": { - "message": "指定圓心和圓周上一點作為零度位置。刻度單位為度。(拖曳或點擊以創建。)" - }, - "tool_Detector_popover": { - "message": "測量通過一線段的能量流率(P)、垂直動量流率(F⊥)與水平動量流率(F∥)。(拖曳或點擊以創建該線段。)單位為任意。" - }, - "tool_Detector_info_popover": { - "message": "
  • P: 能量流率(通量),單位為 B/s(見下文)。
  • F⊥: 垂直動量流率,單位為 (B/s)/c。
  • F∥: 平行動量流率,單位為 (B/s)/c。
  • 匯出的 CSV 中的輻照度單位為 (B/s)/L。
  • L 是本模擬器中使用的任意長度單位。
  • B 是輻射通量或光通量的任意單位,對應到「亮度」選項的單位:非朗伯光束為 B/L,點光源為 500B/360°。
  • 無因次因子 s 是「設定」->「顯示狀態欄」中顯示的「亮度尺度」,當「光線密度」高於某個閾值時為 1,否則與「光線密度」成正比。
  • 如果某些光線在內反射的無窮級數中被截斷,則總截斷量將顯示為誤差估計。
" - }, - "tool_TextLabel_popover": { - "message": "文字標籤。" - }, - "tool_LineArrow_popover": { - "message": "線段或箭頭。(拖曳或點擊以創建。)" - }, - "tool_Drawing_popover": { - "message": "手繪工具。(拖曳以繪圖。)" - }, - "tool__popover": { - "message": "拖曳以移動視窗。(滑鼠右鍵拖曳也有相同的功能)" - }, - "mode_rays_popover": { - "message": "畫出光線。當「光線密度」高時,光線呈現連續。" - }, - "mode_extended_popover": { - "message": "除光線實際路徑外,亦畫出其延長線。橘色、灰色分別表示向後、向前的延長線。
若使用「模擬色彩」,則改以光源顏色顯示並以虛線區分。" - }, - "mode_images_popover": { - "message": "點出像的位置。黃點表示實像,橘點表示虛像,灰點(圖中沒有)表示虛物。注意「光線密度」不夠高時有些像無法正常顯示。
若使用「模擬色彩」,則改以光源顏色顯示並以點的大小區分。" - }, - "mode_observer_popover": { - "message": "模擬從某位置見到的光線與像。藍色圓形為觀察者,與其相交的光線被其「觀察」到。觀察者無法知道光線真正的起始位置,但若其在某處相交,它會認為光線是從該處來的。光線以藍色表示,相交處以黃色(實像)或橘色(虛像)表示。(拖曳大藍點以移動觀察者。)
若使用「模擬色彩」,則改以光源顏色顯示。" - }, - "simulateColors_popover": { - "message": "模擬光源的顏色(波長)、混色、遮光物與鏡子的濾光,以及透光物的色散。選取物件後可調整這些參數。重疊多條不同波長的光線可用於模擬光譜。螢幕顯示之顏色僅為粗略近似,且當「光線密度」太高或太低時可能非常不準確。" - }, - "rayDensity_popover": { - "message": "決定從光束與點光源射出的光線數量。這也會影響到像的偵測與顏色渲染的準確性。" - }, - "showGrid_popover": { - "message": "決定是否顯示背景格線。" - }, - "grid_popover": { - "message": "決定是否對齊格線。" - }, - "lockObjs_popover": { - "message": "決定物件是否能被移動。" - }, - "zoom_popover": { - "message": "透過百分比縮放視窗。" - }, - "help_popover": { - "message": "限制拖曳行為

拖曳物件時,按住 Shift 以限制於水平或垂直移動;按住 Ctrl 以複製物件。建立線型物件或拖曳其端點時,按住 Shift 以鎖定角度或吸附至 0°、45°、90°;按住 Ctrl 以對於中心點旋轉或縮放。

群組、旋轉及縮放物件

按住 Ctrl,點擊多個控制點(如端點),並點擊空白處以將這些點群組並建立控制桿。拖曳控制桿(或按方向鍵)以平移群組;Shift+拖曳以限制於水平或垂直移動;Ctrl+拖曳以旋轉;Ctrl+Shift+拖曳以縮放。移動「+」以設定旋轉或縮放中心。點擊控制桿並按 Ctrl+D 以複製群組;按 Delete 以解散群組。

直接編輯座標

對控制點(如端點)點兩下或按右鍵,輸入 (x,y) 座標,然後按 Enter。

鍵盤快速鍵

當一物件在被選取的狀態(被點擊)時,按方向鍵以移動;Ctrl+D 以複製;Delete 以刪除。

聯絡我們

建議使用 GitHub 上的 DiscussionsIssues 功能(請使用英文)。若您對 GitHub 不熟,也可發送電子郵件至 ray-optics@phydemo.app(可使用中文)。

也歡迎直接進行貢獻(見貢獻指南)。

" - }, - "show_help_popups": { - "message": "顯示提示泡泡" - }, - "show_help_popups_popover": { - "message": "決定滑鼠移到按鈕上方時是否顯示提示泡泡(須重新載入網頁以套用變更)" - }, - "show_json_editor": { - "message": "顯示 JSON 編輯器Beta" - }, - "show_json_editor_popover": { - "message": "顯示表達場景原始碼的 JSON 編輯器。在建立自訂模組時需要使用(見工具->其他->匯入模組->建立自訂模組)。" - }, - "show_status": { - "message": "顯示狀態方塊" - }, - "show_status_popover": { - "message": "顯示狀態方塊,其中包含滑鼠座標,效能資訊,以及被截斷的亮度(光線在內反射的無窮級數中被截斷的總亮度)。" - }, - "auto_sync_url": { - "message": "自動同步網址" - }, - "auto_sync_url_popover": { - "message": "啟用時,網址會隨著場景自動更新,而不必持續手動儲存場景。如需設定標題,請用檔案->儲存->重新命名。" - }, - "auto_sync_url_warning": { - "message": "本場景過大,無法與網址同步。請自行儲存場景。" - }, - "gridSize": { - "message": "格線大小" - }, - "observer_size": { - "message": "觀察者大小" - }, - "language": { - "message": "語言" - }, - "close": { - "message": "關閉" - }, - "advanced_help": { - "message": "進階說明詳見右下角的說明圖示。" - }, - "ray_count": { - "message": "光線片段數量:" - }, - "total_truncation": { - "message": "被截斷的亮度:" - }, - "brightness_scale": { - "message": "亮度尺度:" - }, - "time_elapsed": { - "message": "花費時間(ms):" - }, - "force_stopped": { - "message": "已強制終止。" - }, - "mouse_coordinates": { - "message": "滑鼠座標:" - }, - "modules_tutorial": { - "message": "製作自訂模組" - }, - "modules_tutorial_url": { - "message": "https://phydemo.app/ray-optics/tw/modules/tutorial" - }, - "identical_optical_objects_warning": { - "message": "場景中有兩個完全相同的光學元件完全重合。這可能會導致非預期的行為。" - }, - "import_modules": { - "message": "匯入模組..." - }, - "import_modules_title": { - "message": "匯入模組" - }, - "modules_url": { - "message": "../tw/modules/modules.html" - }, - "remove_module": { - "message": "移除模組" - }, - "module_conflict": { - "message": "場景中已有一個同名但不相同的模組。您可以指定新的名稱,或保留相同名稱以取代原模組。" - }, - "brightness_inconsistent_warning": { - "message": "有至少兩個光源的亮度以不一致的比例達到飽和。這可能會導致探測器的讀數與色彩渲染錯誤。請提高光線密度或降低光源亮度。" - } -} \ No newline at end of file diff --git a/locales/zh-TW/gallery.json b/locales/zh-TW/gallery.json new file mode 100644 index 00000000..98db7d40 --- /dev/null +++ b/locales/zh-TW/gallery.json @@ -0,0 +1,486 @@ +{ + "galleryPage": { + "title": "「線光學模擬」作品集", + "description": "以下列表為使用[「線光學模擬」網頁程式](/simulator)製作的互動式光學演示。歡迎您貢獻新項目(請參閱[貢獻指南](/contributing/gallery))。如發現內容有誤,請[在GitHub上建立Issue](/github/issues)或發送電子郵件至[ray-optics@phydemo.app](/email)。", + "categories": { + "title": "類別", + "reflection": "光的反射", + "refraction": "光的折射", + "lens": "透鏡", + "combinationOfLenses": "透鏡組合", + "grinOptics": "漸變折射率光學", + "miscellaneous": "其他" + }, + "contributors": "貢獻者:{{contributors}}", + "openInSimulator": "在模擬器中開啟" + }, + "galleryData": { + "common": { + "warningthesequenceof": "警告:光線出現的順序並不代表實際的光速。只有最終的圖像有意義。" + }, + "imagesFormedByTwoMirrors": { + "title": "兩面鏡子成像", + "description": "本模擬項目顯示了兩面鏡子所成的像,其中綠色的 L 為物。若兩面鏡子的夾腳為 \\(\\frac{360^\\circ}{n}\\) 那麼將成\\(n-1\\) 個虛像(橘色的 L)。可拖曳鏡子端點來改變夾角。" + }, + "parabolicMirror": { + "title": "拋物面鏡", + "description": "此模擬示範了拋物面鏡的聚焦特性。" + }, + "hyperbolicMirror": { + "title": "雙曲面鏡", + "description": "本模擬示範了雙曲面鏡的反射特性:從一個焦點向雙曲面鏡傳播的光線將如同從另一個焦點射出。\n\n雙曲面的兩個焦點是等光程點(請參閱[ 等光程點](/gallery/aplanatic-points))。", + "theorangeraysareimag": "橙色線是黃色反射光線的延長線。\n這些虛射線在另一個焦點上匯合。", + "pointlightsourceaton": "位於一個焦點的點光源" + }, + "retroreflectors": { + "title": "回復反射器", + "description": "這是兩種回復反射器的模擬:\n\n1. 角隅反射器。\n2. 貓眼回復反射器。", + "dragtorotatethebeam": "拖曳此處\n可旋轉光束", + "catseyeretroreflecto": "貓眼回覆反射器", + "cornerretroreflector": "角隅反射器" + }, + "periscope": { + "title": "潛望鏡", + "description": "這是一個由兩面平鏡和一些光線阻擋器製成的潛望鏡模擬。", + "observerseyenottosca": "觀察者的眼睛(非按比例)" + }, + "newtonianTelescope": { + "title": "牛頓望遠鏡", + "description": "這是一個配有Plössl目鏡的牛頓望遠鏡模型。" + }, + "penroseUnilluminableRoom": { + "title": "無法照亮的潘洛斯房間", + "description": "無法照亮的潘洛斯房間由橢圓形、圓形和線性鏡子構成。它有一個有趣的特性,即房間內的一個點源(綠色)無論放在哪裡,都不會照亮整個房間。您可以拖動綠色點以移動源。", + "nomatterwhereyouputt": "無論您將點光源放在哪裡,它都不會照亮整個房間。\n警告:由於數值誤差,可能會在一段時間後仍然照亮。" + }, + "opticalCavity": { + "title": "雙鏡共振腔", + "description": "模擬由兩面鏡子組成的共振腔。假設腔體的長度為\\(d\\),其鏡子的曲率半徑分別為\\(R_1\\)和\\(R_2\\)(根據慣例,\\(R>0\\)為凹面鏡),那麼只有當\\(0\\leq (1-\\frac {d}{R_1})(1-\\frac {d}{R_2})\\leq 1\\)時,共振腔才會穩定(這意味著從一面鏡子向另一面鏡子發出的每一道光線都保證有非發散的軌跡,前提是鏡子的反射率足夠高)。在此模擬中,我們假設鏡子是理想曲面鏡,這意味著\\(f=\\frac{R}{2}\\),將先前的穩定條件變為\\(0\\leq (1-\\frac {d}{2f_1})(1-\\frac {d}{2f_2})\\leq 1\\)。[這裡](/gallery/resonator)有一個使用球面鏡的類似模擬,在抛物面近似下,第一種穩定條件成立。", + "clickholdleftmouseto": "點擊 + 按住左鍵\n以移動光線", + "dragtomovetheidealmi": "拖曳此處\n可水平移動鏡子", + "d400intheresonatorsb": "下方的共振腔中d = 400", + "confocalresonator": "焦聚共振腔", + "concentricresonator": "共心共振腔", + "concaveconvexresonat": "凹凸共振腔", + "planoconcaveresonato": "平凹共振腔" + }, + "resonator": { + "title": "平凹共振腔", + "description": "這是一個平凹共振腔的演示。如果鏡子間的距離大於曲率半徑,共振腔將會不穩定。如果鏡子間的距離小於或等於曲率半徑,就會形成穩定的共振腔模式。", + "flatmirror": "平面鏡", + "sphericalconcavemirr": "球形凹面鏡", + "unstableresonator": "不穩定的共振腔", + "stableresonator": "穩定的共振腔" + }, + "mazeSolution": { + "title": "用一條光線解迷宮", + "description": "此模擬中,一條光線在迷宮內部產生,並被牆壁多次反射。迷宮內的大紅色和小紅色正方形(如下面的截圖所示)分別代表光線的起源和初始方向。取決於光線初始方向,光線可能最終會離開迷宮,因此原則上可以通過追蹤光線的路徑計算出迷宮的解法。", + "controltherayorigina": "通過分別拖曳此兩標記\n以調整光線的初始點與方向。", + "notethatthesimulatio": "請注意,只有當左下角的「處理中…」\n消失時,才代表模擬完成。", + "mazeexit": "迷宮出口" + }, + "specularAndDiffuseReflection": { + "title": "鏡面反射與漫反射", + "description": "相同的光束照射在光滑表面和粗糙表面上,展示了鏡面反射與漫反射之間的區別。", + "specular": "鏡面反射", + "diffuse": "漫反射" + }, + "chaffCountermeasure": { + "title": "干擾箔", + "description": "這是一個箔片反射對雷達效應的定性模擬(忽略繞射效應)。", + "plane": "飛機", + "radar": "雷達", + "chaff": "箔片", + "selectthechafftochan": "選取箔片可改變箔片數量(N)和長度(L)。" + }, + "causticsFromAReflectiveSphere": { + "title": "反射性球體的焦散", + "description": "一個反射性的積分球。也可以是液滴(如雨滴)中的反射。移動點光源的位置可以看到許多漂亮的圖樣。", + "movethepointsourcear": "移動點光源以觀看焦散及節點\n在積分球中是如何變換的。\n改變遮光物的大小與位置,\n以及球的開口大小來觀察更多效果。" + }, + "theMirascope": { + "title": "幻象鏡", + "description": "**幻象鏡** 是一種有趣的光學幻覺演示裝置,它利用兩個面對面的拋物面鏡來產生一個立體懸浮影像的幻覺。該裝置由以下部件構成:\n1. **兩個拋物面鏡**:大小完全相同,一個朝上,一個朝下,形成貝殼狀結構。這些鏡子被設計成讓光聚焦於特定點。頂部的鏡子在其頂點處有一個孔,讓光線進入裝置。\n2. **一個小物體**:放置在幻象鏡內,通常位於頂部鏡子的焦點附近,其非常接近底部鏡子的頂點。\n\n當來自物體的光線在兩個鏡子之間反射時,它的方向會改變為形成一個看似逼真、立體的影像,懸浮於幻象鏡的表面上方。這種幻象如此逼真,人們常常試圖觸摸影像,結果發現什麼也沒有。\n\n幻象鏡被廣泛用於科學演示、玩具及新奇物品,以說明光學中反射和光線行為的原理。", + "object1": "物體", + "realimage1": "實像" + }, + "reflect": { + "title": "反射與折射", + "description": "此模擬顯示了光經過界面的反射和折射。" + }, + "internalReflection": { + "title": "全反射", + "description": "此模擬顯示了光經過界面的折射和內部反射,包括全反射。" + }, + "prisms": { + "title": "稜鏡", + "description": "此模擬演示了直角稜鏡(right-angle prism)、波羅稜鏡(Porro prism)、菱形稜鏡(rhomboid prism)、杜福稜鏡(Dove prism),和五面稜鏡(pentaprism)。", + "rhomboid": "菱形", + "rightangle": "直角", + "porro": "波羅", + "dove": "杜福", + "pentaprism": "五面" + }, + "beamDirectors": { + "title": "光束導向器", + "description": "這是一個普通雙棱鏡 (biprism) 和菲涅耳雙稜鏡(Fresnel biprism)的模擬。雙棱鏡可以將入射的平行光束導向兩個方向,其取決於頂角的大小。", + "thisfresnelbiprismwa": "這個菲涅耳雙稜鏡是由上面的雙稜鏡製成\n您可以選取雙稜鏡並調整 N_silce(切片數量)參數。", + "fresnelbiprism": "菲涅耳雙稜鏡", + "biprism": "雙稜鏡" + }, + "apparentDepth": { + "title": "視深度", + "description": "當您從空氣中觀察水下的物體時,物體的深度會看似小於其實際深度。本模擬示範了這種由光的折射造成的現象。視深度與觀察者的位置有關,這點我們可以通過拖動藍色圓圈來演示。", + "observedimageorange": "觀察到的像(橘點)", + "observer": "觀察者", + "objectunderwatergree": "水中物體(綠點)" + }, + "bendedPencil": { + "title": "彎曲的鉛筆", + "description": "從上方觀察部分浸入水中的鉛筆,因為空氣和水之間的折射指數的不連續性,我們的眼睛會感覺到鉛筆看起來既斷裂又彎曲。然而,在這個模擬中,彎曲的現象更為明顯。您可以查看斷裂的鉛筆模擬,那裡的斷裂現象更為明顯。", + "bentpencilyellowimag": "彎曲的鉛筆(黃色)\n視網膜上的影像", + "dielectricmaterial": "電介質材料", + "originalpencilgreen": "原始鉛筆(綠色)", + "observerseye": "觀察者的眼睛", + "ignoretheorangesquar": "忽略橙色的正方形!" + }, + "brokenPencil": { + "title": "斷裂的鉛筆", + "description": "從側面觀察部分浸入水中的鉛筆,因為空氣和水之間的折射指數的不連續性,我們的眼睛會感覺到鉛筆看起來既斷裂又彎曲。然而,在這個模擬中,斷裂的現象更為明顯。您可以查看彎曲的鉛筆模擬,那裡的彎曲現象更為明顯。", + "brokenpencilyellowim": "斷裂的鉛筆(黃色)\n視網膜上的影像" + }, + "chromaticDispersion": { + "title": "色散", + "description": "這個模擬使用一個白色光束和一個三角稜鏡展示色散現象。此處白色是由紅、橙、黃、綠、青、藍、紫的混色形成的。", + "dragheretoadjustbeam": "拖曳此處\n可調整光束寬度", + "dragheretorotatethep": "拖曳此處\n可旋轉棱鏡" + }, + "rainbows": { + "title": "彩虹", + "description": "本模擬演示了虹、霓以及亞歷山大暗帶是如何形成的。這裡,我們以紅、橙、黃、綠、青、藍、紫的混色來近似陽光的光譜。對於虹/霓,離開雨滴的光線是由雨滴內部的一次/兩次內部反射產生的(你可以通過將光線密調低並拖動雨滴來觀察這一點)。請注意,這些並不是全內反射,因此出射光線的強度遠低於入射光線。由於[最小偏向角](/gallery/minimum-deviation-angle)與波長有關,不同顏色的光線會在不同的角度堆積,於是彩虹中的顏色就產生了。遠離最小偏向角時,光線不會堆積,所以所有顏色都很弱並混合在一起,使得在兩彩虹之外的角度產生昏暗的白色(或「灰色」)。相較之下,虹與霓之間則沒有這樣的光線,於是形成亞歷山大暗帶。", + "thesearethecolorspro": "以上是由單個雨滴產生的顏色。\n我們最終看到的彩虹是由天空中大量的雨滴產生的,\n每個都對觀察者呈現單一一種顏色(在相應的角度)。", + "secondaryrainbow": "霓", + "alexandersdarkband": "亞歷山大暗帶", + "raindrop": "雨滴", + "primaryrainbow": "虹", + "sunlight": "陽光" + }, + "minimumDeviationAngle": { + "title": "最小偏向角", + "description": "光線射到光學元件上的偏向角有多種定義。下方的截圖中可以看到對於三棱鏡和球形透鏡的定義。在本模擬中,光線進入光學元件的入射角與偏向角之間的關係在某個角度有局部極小值,這個偏向角被稱為「最小偏向角」。這個局部極小值可以解釋如[彩虹](/gallery/rainbows)和光暈這樣的光學現象。由於這個局部極小值,偏轉的光線在特定的方向上堆積,產生「光學焦散」(如在模擬中的例子C中看到的)我們會將其視為彩虹/光暈。", + "inexamplesaandbbyrot": "在例A和B中,通過在點A1到A2和B1到B2之間旋轉稜鏡,改變光線進入光學元件的\n入射角,你可以清楚地看到一個最小的\n偏向角出現在兩點之間的某處。\n(在例A中,偏向角為相對於水平軸測量,而在例B中,\n偏向角為相對於垂直軸測量)。\n現在請看例C(可用縮放功能拉近),並將兩束光擴展(紅色和紫色,\n重疊部分呈現粉紅色。這與例B中旋轉棱鏡\n的效果相同,故是在改變入射角),並觀察從點\nC1到C2之間的反向出射光線向下堆積於兩個明顯的紅色和紫色\n線(「光學焦散」)- 最小偏向角出現在點C2附近,並與\n光的波長(顏色)有關。然後,把光束從C2擴展到C3時,它們的\n反向出射光線的方向反轉為向上。", + "examplea": "例A", + "examplec": "例C", + "exampleb": "例B", + "dragtorotate": "拖曳以旋轉", + "dragtoadjustbeamwidt": "拖曳以調整光束寬度", + "usethebuiltinzoomtob": "建議使用模擬器內建的縮放功能以利觀察", + "deviationangle": "偏向角", + "incidenceangle": "入射角" + }, + "aplanaticPoints": { + "title": "等光程點", + "description": "光學系統的等光程點是其光學軸上的特殊點,即「從其中一點發出的光線會匯聚到另一點,或看似從從該點發散」。\n\n- 橢圓:橢圓鏡片/鏡子的兩個焦點是等光程點,因為從一個焦點發出的光將匯聚向另一點。\n- 球體:球形透鏡有兩個等光程點,分別在球內和球外 - 更多細節請見模擬。\n- 雙曲線:在[雙曲面鏡](/gallery/hyperbolic-mirror)模擬中的兩個焦點也是等光程點。\n\n給定兩個擁有水平座標 \\(x_1\\) 和 \\(x_2\\) 、具有相同垂直座標的點,並且設光學元件外部和內部的折射率分別為 \\(n_1\\) 和 \\(n_2\\),則若這兩點要成為等光程點,我們的光學元件的邊界必須滿足\\begin{equation}k_1 n_1 \\sqrt{ (x - x_1)^2 + y^2} + k_2 n_2 \\sqrt{ (x - x_2)^2 + y^2} = E\\end{equation}使得 \\(k_i=1\\) 或 \\(-1\\)(取決於連接 \\(x_i\\) 和我們的光學元件邊界的光線是實的或虛的),而 \\(E\\) 是一個使這個方程有非平凡解的常數。這個方程(可以用費馬原理推導出來)是笛卡爾卵形線的方程(圓錐曲線是其特例)。", + "clickontheextendedra": "點選「延長光線」按鈕以驗證從球面鏡片中的光源(點 A)發出的光,\n是從球面鏡片外的光學軸上的另一點(點 B)發散,無球面像差。\n點 A 和 B 是球體的等光程點的例子。對於此點,在標記的 Y 軸的相對座標中(k1, k2, n1, n2, x1, x2, E)=(1, -1, 1.5, 1, 3 * 20, -4.5 * 20, 0),\n其中 x1,x2 是點 A,B 的水平座標(每個格線單元的尺寸為 20x20)。\n同樣地,橢圓的焦點(點 C 和 D)是橢圓的等光程點的例子,對於此點(k1, k2, n1, n2, E)=(1, 1, 1.5, 1.5, > 0)", + "sphericallens": "球面透鏡", + "ellipticallens": "橢圓透鏡", + "yaxis": "Y 軸" + }, + "concaveLens": { + "title": "凹透鏡", + "description": "模擬凹透鏡使光束分散的現象。" + }, + "convexLens": { + "title": "凸透鏡", + "description": "模擬凸透鏡使光束聚焦的現象。" + }, + "lensImages": { + "title": "透鏡成像", + "description": "模擬理想透鏡成像,包括平行光與點光源成的像。" + }, + "transverseAndLongitudinalMagnification": { + "title": "橫向和縱向放大率", + "description": "模擬焦距為 \\(f\\) 的理想透鏡的橫向和縱向放大率。橫向(也稱為線性)和縱向的放大率分別是 \\(M_T=1-\\frac{u}{f}\\) 和 \\(M_L=\\frac{dv}{du}\\),其中 \\(u\\) 和 \\(v\\) 分別是物體和圖像距離我們的理想透鏡的距離。另外,對於理想透鏡,\\(M_L=-(M_T)^2\\)", + "inthisexamplewehavey": "在這個例子中,我們有 y'_j - y'_k = M_T * (y_j - y_k),其中 j,k∈{0,1,2,3,4,5}。\n因此,例如點物體(x_0,y_0)的橫向放大率是 M_T = -3,我們可以計算 -\n(x'_0 - x'_1)/(x_1 - x_0) ≈ -0.3699\n(x'_0 - x'_2)/(x_2 - x_0) ≈ -0.7297\n(x'_0 - x'_3)/(x_3 - x_0) ≈ -1.4211\n(x'_0 - x'_4)/(x_4 - x_0) ≈ -2.4545\n(x'_0 - x'_5)/(x_5 - x_0) = -5.4\n.\n.\n.\n(這個比值將趨近於縱向放大率:M_L = - (M_T)^2 = -9)", + "rightclickonarealobj": "在(實)物上點擊右鍵以查看其座標。\n綠色的方塊是實際的點光源,黃色的方塊是像。" + }, + "vanishingPoint": { + "title": "消失點", + "description": "有些光學系統將無限的平行線映射到影像平面上的一些線,使得這些線在一個點上相交,於是產生一種平行線在「無窮遠處」相交的幻覺。這個交點被稱為消失點。\n\n考慮一個由焦距為 \\(f\\) 的理想透鏡組成,位於 \\(XY\\) 平面上,光學軸與 \\(X\\)(水平)軸重合,透鏡與 \\(Y\\) 軸重合的光學系統。對於斜率為 \\(m\\) ,位於 \\(x<0\\) 的線,其消失點之 \\((x,y)\\) 座標為 \\((f,m f)\\) 。", + "youcanverifythatapai": "你可以驗證一對斜率為 m 的平行線,經過理想透鏡收斂到座標 (f,m∙f),\n通過點擊「格線」按鈕,並注意到每個格線單元的尺寸為20乘以20。\n你也可以驗證改變理想透鏡的焦距 f 時,收斂點(消失點)會如何受到影響。", + "thesepairofparallell": "這對平行線聚集到點B", + "thesepairofparallell1": "這對平行線聚集到點A", + "notethatthesepairsof": "注意這些平行線實際上並不是無窮大。" + }, + "monochromaticAberrations": { + "title": "單色像差", + "description": "這是不同單色像差的模擬:\n\n1. 球面像差(Spherical aberration)。\n2. 彗形像差(Coma aberration)。\n3. 散焦像差(Defocus aberration)。\n4. 場曲像差(Field curvature aberration)。", + "defocusaberration": "散焦像差", + "sphericalaberration": "球面像差", + "screen": "屏幕", + "fieldcurvatureaberra": "場曲像差", + "commaaberration": "彗形像差" + }, + "chromaticAberration": { + "title": "色像差", + "description": "此模擬顯示了球面透鏡的色像差(Chromatic aberration)。這裡的白色是由紅、橙、黃、綠、青、藍、紫混色形成的。紅光的焦距最大,而紫光的焦距最小。", + "dragtoadjustbeamwidt1": "拖曳此處可調整光束寬度" + }, + "hyperbolicLens": { + "title": "雙曲透鏡", + "description": "這是雙曲透鏡與球面透鏡的對比。這兩個透鏡有相同的焦距,但雙曲透鏡可以將單色光的平行光束集中到一點(忽略光的波動性 - 也就是在幾何光學的近似下)而不像球面透鏡會有有球面像差(Spherical aberrations)。", + "thefocallengthofthis": "此球面透鏡的焦距(在近軸近似中)為:\nf=R/(n-1)=200/(1.5-1)=400", + "thefocallengthofthis1": "此雙曲透鏡的焦距是:\nf = |C| ∙ sqrt(n^2 - 1) / (n - 1) = K ∙ sqrt(0.8) ∙ sqrt(1.5^2 - 1) / (1.5 - 1) = 400\n此雙曲透鏡的方程式是:\ny(x) = (a/K) - sqrt( ((x/K)^2 + (C/K)^2) / (n^2 - 1) )\n= 1.5 - sqrt( (0.8 + (x / 200)^2) / (1.5^2 - 1) )\n使得K是方程式維度與網格維度之間的轉換常數 - 對於這個雙曲面鏡,K=20\n(例如0 0\\) 且 \\(\\alpha = \\arctan k\\) 為等角螺線與同心圓形的交點上兩切線的固定夾角,見[這個](https://en.wikipedia.org/wiki/Logarithmic_spiral#/media/File:Logspiral.gif)動畫)的折射率函數為 \\(n(r) ∝ \\frac{1}{r} \\) (這可用將光線路徑以極座標表示並使用費馬原理來證明)。", + "thecircularblockeris": "中央的圓形遮光物是為了\n避開折射率的奇異點", + "dragtochangetheiniti": "拖曳此處可改變\n光線的初始方向", + "youcanselectthegring": "您可以選擇漸變折射率透光物\n並更改數值求解器的步長" + }, + "luneburgLens": { + "title": "龍伯透鏡", + "description": "龍伯透鏡(Luneburg lens)是一個球形介電材料,折射率為 \\(n(\\rho) = \\sqrt{n_0-(\\frac{\\rho}{R})^2} \\),其中 \\(n_0=2\\) 是其球心的折射率,\\(R=100\\) 是球的半徑,\\(\\rho\\) 是與球心的距離。\n\n上方的介電材料為由 \\(N=20\\) 個同心球組成的龍伯透鏡,半徑 \\(R_i=5(N+1-i)\\),折射率 \\(n_i = \\sqrt{n_0-(\\frac{R_i}{R})^2} \\),其中 \\(i=1,...,N\\)。然而,由於此模擬器會將互相重疊的光學元件的折射率相乘,所以第 \\(i\\) 個同心球形鏡的數值折射率為 \\(n_{i}^\\text{numerical}=\\frac{n_i}{n_{i-1}}\\)。\n\n下方的介電材料是折射率為\\(n(r)\\)的漸變折射率材料。", + "approximatedmultilay1": "用多層近似的龍伯透鏡(您可以選擇並更改層數 N)", + "classicalluneburglen": "正統的龍伯透鏡(您可以選擇並更改數值求解器的步長)" + }, + "maxwellFisheyeLens": { + "title": "馬克士威魚眼透鏡", + "description": "馬克士威魚眼透鏡(Maxwell fisheye lens)是一個球形介電材料,折射率為 \\(n(\\rho) = \\frac{n_0}{1+(\\frac{\\rho}{R})^2} \\),其中 \\(n_0=2\\) 是其球心的折射率,\\(R=100\\) 是球的半徑,\\(\\rho\\) 是與球心的距離。\n\n上方的介電材料為由 \\(N=20\\) 個同心球組成的馬克士威魚眼透鏡,半徑 \\(R_i=5(N+1-i)\\),折射率 \\(n_i = \\frac{n_0}{1+(\\frac{R_i}{R})^2} \\),其中 \\(i=1,...,N\\)。然而,由於此模擬器會將互相重疊的光學元件的折射率相乘,所以第 \\(i\\) 個同心球形鏡的數值折射率為 \\(n_{i}^\\text{numerical}=\\frac{n_i}{n_{i-1}}\\)。\n\n下方的介電材料是折射率為\\(n(r)\\)的漸變折射率材料。", + "approximatedmultilay2": "用多層近似的馬克士威魚眼透鏡(您可以選擇並更改層數 N)", + "classicalmaxwellfish": "正統的馬克士威魚眼透鏡(您可以選擇並更改數值求解器的步長)" + }, + "branchedFlow": { + "title": "分支流", + "description": "當光線經過折射率在空間上有隨機擾動(相關長度遠大於光的波長)的介質時,會形成一種類似樹狀的圖案,稱為分支流。本模擬使用一些餘弦函數的和作為折射率函數來演示這個現象,其中餘弦函數的振幅、波數與相位都是類似隨機的數。" + }, + "singleRayDemo": { + "title": "單一光線演示", + "description": "本模擬示範了一條光線的反射和折射。" + }, + "sphericalLensAndMirror": { + "title": "球面透鏡與面鏡", + "description": "這個模擬演示了一束連續的光線穿過一個球面透鏡和一個球面面鏡。" + }, + "interrogationRoom": { + "title": "審訊室", + "description": "這是一個審訊室雙向鏡的模擬。在黑暗的房間裡的觀察者(理想情況下,黑暗的房間內部不會發出/反射光,同時會吸收來自審訊室的所有入射光)能夠通過雙向鏡看到審訊室內部,因為審訊室裡的燈產生的光被散射並由觀察者接收,而嫌疑人只能看到審訊室內部以及他/她和燈的反射(因為嫌疑人未從黑暗的房間接收到光)。", + "pressonallimagestose": "按下「所有像」以查看\n燈的反射以及嫌疑人和觀察者\n構成的的影像平面中物體的位置", + "darkroom": "黑暗的房間", + "twowaymirror": "雙向鏡", + "lamp": "燈", + "interrogationroom": "審訊室", + "observerseyeris": "觀察者的眼睛", + "suspectseyeris": "嫌疑人的眼睛", + "thelampobjectinthesu": "嫌疑人的影像平面中的燈物體", + "thelampsreflectionin": "嫌疑人的影像平面中的燈的反射", + "thelampsreflection": "燈的反射", + "thelampobjectintheob": "觀察者的影像平面中的燈物體" + }, + "cameraObscura": { + "title": "暗箱", + "description": "這是一個暗箱的模擬。在黑暗的房間裡的觀察者看到的是外面物體的倒置影像,並且這個影像是直接投影在他/她前面的牆壁上的(無需使用額外的透鏡)。", + "observer2": "觀察者", + "objectsoutside": "外面的物體", + "darkroom1": "黑暗的房間" + }, + "thePrincipleOfCameraImaging": { + "title": "相機成像原理", + "description": "此範本提供了一種互動式方法來學習相機成像原理,涵蓋焦距、光圈、感測器靈敏度和背景模糊等基本主題,對學生和愛好者都有幫助。", + "camera": "相機", + "cmos": "CMOS" + }, + "nlSimulation": { + "title": "NL 雙筒望遠鏡", + "description": "這個模擬展示了 Swarovski NL 雙筒望遠鏡的粗略草圖。" + }, + "einsteinRingRefocusedToSingleImageViaEyepiece": { + "title": "經由目鏡將愛因斯坦環重新聚焦為單一影像", + "description": "這是一個目鏡/透鏡的模型,可以用在任何科學望遠鏡上,透過逆轉「光暈」,將愛因斯坦環聚焦回原始形態,同時散射用來創建環的星體或大質量物體的光。" + }, + "blackCatBecomesWhite": { + "title": "「黑貓變白貓」演示", + "description": "「黑貓變白貓」是一個科普演示。當圖畫浸入水中時有部分會消失。製作步驟如下:\n\n1. 在紙上繪製圖案(如黑貓)。\n2. 將紙放入塑膠套中。\n3. 在塑膠套上描出該圖案的一部分(如貓的邊框)或其他圖案。當放入水中時,繪製在紙上的圖案將消失,但繪製在塑膠套上的圖案不會消失。\n\n本模擬解釋它的原理。", + "whenthebagisunderwat": "當塑膠套在水中時,來自紙上的光無法到達眼睛,\n故我們只看到畫在塑膠套上的圖案。", + "lightfromtheplastics": "來自塑膠套上的光", + "lightfromthepaper": "來自紙上的光", + "eyes": "眼睛", + "dragtomovethebagouto": "拖曳此處可將塑膠套移出水面" + }, + "dichroicRbgSplitterAndCombiner": { + "title": "二色性RGB分光器與合光器", + "description": "這個模擬使用二色鏡來分割和組合RGB光束。", + "rgbcomponentsplitter": "RGB分量分光器與合光器", + "lightsource": "光源", + "dichroiccube": "二色性立方體", + "beamcombiner": "合光器" + }, + "ganBasedLcdPixel": { + "title": "液晶螢幕像素", + "description": "這是一個液晶螢幕像素的模型。它模擬了新型的微型發光二極體顯示層的功能,以及我們的眼睛是如何感知它的。", + "pixelsaresosmallthel": "由於像素非常小,光\n在我們的眼中看起來是混合的", + "changetherateoftrans": "改變透光率\n來產生任何RGB值", + "blueledbacklight": "藍色LED背光", + "yellowphosphor": "黃色磷光體", + "liquidcrystal": "液晶", + "lightfilters": "濾光器", + "pixelasvisibletoview": "觀察者看到的像素", + "notpartoflcddisplay": "不是液晶顯示器的一部分" + }, + "concaveMirrorWearableDisplay": { + "title": "凹面鏡可穿戴顯示器", + "description": "簡易的可穿戴顯示器。許多設計都使用兩個鏡子及一個正透鏡,但本模擬為只用一個光學元件的版本。比例約為 5:1mm。\n\nCC0:此作品已被標記為釋出至公有領域", + "tft09display": "TFT 0.9吋顯示器", + "concavemirror": "凹面鏡", + "eye1": "眼睛", + "nose": "鼻子", + "pointsourcetomeasure": "用來測量半徑的點光源", + "t15readingglasses": "+1.5度閱讀眼鏡" + }, + "reflectingMonochromator": { + "title": "反射式單色儀", + "description": "這是一個反射式單色儀的模擬,其透過反射式繞射光柵與聚焦處的出射口,從多波長混合的光之中取得窄頻寬的光。", + "reflectingmonochroma": "反射式單色儀", + "rotatediffractiongra": "旋轉繞射光柵\n以從多波長混合的光\n之中取得窄頻寬的光", + "exitslitmonochromati": "出射口\n\n單色光" + }, + "solarEclipses": { + "title": "日食", + "description": "本模擬演示了不同類型的日食。右上方的圖中,月球的影子遮蔽了太陽,在中心產生了日全食,周圍地區則是日偏食。右下方的圖為日環食,其中由於月球距離地球較遠,無法完全遮蔽太陽,在中心留下一個明亮的環(本二維模擬器中,這個「環」為陽光只來自太陽的最上方與最下方的部分),而周圍地區也是日偏食。", + "nottoscale": "(非按比例)", + "sun": "太陽", + "moon": "月亮", + "partialeclipse": "日偏食", + "annulareclipse": "日環食", + "earth": "地球", + "totaleclipse": "日全食" + }, + "moduleExampleBasics": { + "title": "模組範例 - 基本概念", + "thistextisinexamplem": "這段文字在 ExampleModule 中", + "thistextisalsoinexam": "這段文字也在 ExampleModule 中", + "thistextisnotinamodu": "這段文字不在模組中。", + "thistextisalsonotina": "這段文字也不在模組中。" + }, + "moduleExampleParameters": { + "title": "模組範例 - 參數", + "thismodulehastwopara": "本模組有兩個參數:n=`n` 與 theta=`theta`。\n您可以選取並拖曳數值滑桿來調整它們。", + "thesizeofthistextosc": "這段文字的大小會隨 theta 震盪。" + }, + "moduleExampleControlPoints": { + "title": "模組範例 - 控制點", + "hereisthefirstdragga": "↙這是本模組的第一個(可被拖曳的)控制點", + "hereistheseconddragg": "↙這是本模組的第二個(可被拖曳的)控制點", + "hereisthemidpoint": "↙這是中間點" + }, + "moduleExampleArraysAndConditionals": { + "title": "模組範例 - 陣列與條件", + "a1darrayii": "一維陣列:i=`i`", + "thistextisshownonlyw": "這段文字只在 n>5 時顯示" + }, + "moduleExampleCustomEquation": { + "title": "模組範例 - 自訂數學式", + "amirrorofshapeycos2p": "形狀為 y=cos(2 pi x + `phi`) 的鏡子" + }, + "moduleExampleShapeParametrization": { + "title": "模組範例 - 形狀參數化", + "alensdefinedbydr1r2": "以 d, R_1, R_2 定義的透鏡", + "alensdefinedbydffdbf": "以 d, FFD, BFD 定義的透鏡" + } + } +} \ No newline at end of file diff --git a/locales/zh-TW/main.json b/locales/zh-TW/main.json new file mode 100644 index 00000000..46c9011d --- /dev/null +++ b/locales/zh-TW/main.json @@ -0,0 +1,229 @@ +{ + "meta": { + "languageName": "正體中文", + "parentheses": "{{main}}({{sub}})", + "colon": "{{name}}:{{value}}", + "list": "{{first}}、{{others}}" + }, + "project": { + "name": "線光學模擬", + "shortName": "線光學", + "description": "自由、開源的網頁程式,用於建立及模擬二維幾何光學場景。" + }, + "pages": { + "simulator": "模擬器", + "home": "首頁", + "gallery": "作品集", + "modules": "模組", + "about": "關於", + "github": "GitHub" + }, + "homePage": { + "description": "建立二維幾何光學場景,並即時模擬光線行為。\n完全免費,免下載,原始碼[公開於 GitHub](/github)。", + "launchSimulator": "啟動程式" + }, + "tools": { + "title": "工具", + "categories": { + "lightSource": "光源", + "mirror": "鏡子", + "glass": "透光物", + "blocker": "遮光物", + "other": "其他" + }, + "common": { + "clickInstruction": "點擊以創建。", + "lineInstruction": "拖曳或點擊以創建。", + "circleInstruction": "拖曳或點擊以創建,第一點為圓心,第二點於圓周上。" + }, + "SingleRay": { + "title": "單一光線", + "description": "由兩點決定一條光線。", + "instruction": "拖曳或點擊以創建,第一個點是光源,射向第二個點。" + }, + "Beam": { + "title": "光束", + "description": "由一線段產生平行或發散光束,密度由「光線密度」滑桿決定。" + }, + "PointSource": { + "title": "點光源", + "description": "由一點向四周發射光線,數量由「光線密度」滑桿決定。" + }, + "AngleSource": { + "instruction": "拖曳或點擊以創建,第一個點是光源,射向第二個點。", + "description": "指定發射角之點光源。" + }, + "Mirror": { + "title": "線段", + "description": "模擬光線射到鏡子時的反射。" + }, + "otherMirror": { + "title": "曲線", + "description": "曲線形的鏡子。可選圓弧、拋物線,或自訂函數 y = f(x)。" + }, + "ArcMirror": { + "title": "圓弧", + "description": "圓弧形的鏡子,由三點決定。", + "instruction": "拖曳或點擊兩個端點以創建,然後點擊弧上另一點以決定曲率。" + }, + "ParabolicMirror": { + "title": "拋物線", + "description": "拋物線形的鏡子,由三點決定。", + "instruction": "拖曳或點擊兩個端點以創建,然後點擊頂點。" + }, + "CustomMirror": { + "title": "自訂函數", + "description": "形狀為自訂等式 y = f(x) 的鏡子,其中 (x,y) 為變換過的座標,使得兩控制點為 (-1,0) 及 (1,0)。" + }, + "IdealMirror": { + "title": "理想曲面鏡", + "description": "完全符合面鏡公式(1/p + 1/q = 1/f)的理想化「曲面」鏡,可直接設定其焦距。" + }, + "BeamSplitter": { + "title": "分光鏡", + "description": "能穿透一個比例的光的鏡子。" + }, + "PlaneGlass": { + "title": "半平面", + "description": "模擬光線經過透光物體界面時的反射與折射。", + "instruction": "拖曳或點擊界面上的兩點以創建。" + }, + "otherGlass": { + "title": "其他形狀", + "description": "任何由線段與圓弧組成的透光物,或自訂不等式 f(x) < y < g(x)。" + }, + "CircleGlass": { + "title": "圓形", + "description": "圓形透光物,由圓心與表面上一點決定。" + }, + "Glass": { + "title": "多邊形 / 圓弧", + "description": "任何由線段與圓弧組成的透光物。", + "instruction": "點擊以建立線段,拖曳以建立弧形,點擊一開始的點以結束繪製。" + }, + "CustomGlass": { + "title": "自訂函數", + "description": "形狀為自訂不等式 f(x) < y < g(x) 的透光物,其中 (x,y) 為變換過的座標,使得兩控制點為 (-1,0) 及 (1,0)。" + }, + "IdealLens": { + "title": "理想透鏡", + "description": "完全符合薄透鏡公式(1/p + 1/q = 1/f)的理想化透鏡,可直接設定其焦距。" + }, + "SphericalLens": { + "title": "球面透鏡", + "description": "球面透鏡,其形狀可用多種方式定義。" + }, + "CircleGrinGlass": { + "title": "漸變折射率圓形", + "description": "折射率為自訂函數 n(x,y),邊界為圓形的透光物。" + }, + "GrinGlass": { + "title": "漸變折射率多邊形", + "description": "折射率為自訂函數 n(x,y),邊界為多邊形的透光物。", + "instruction": "點擊以建立線段,點擊一開始的點以結束繪製。", + "warning": "警告:僅支援簡單多邊形,否則行為無法預測。" + }, + "otherGrinGlass": { + "title": "漸變折射率透光物", + "description": "折射率為自訂函數 n(x,y) 的材料。" + }, + "Blocker": { + "title": "吸光片", + "description": "線段形狀的吸光片,光線射到其上後就不會再射出。" + }, + "CircleBlocker": { + "title": "圓形遮光物", + "description": "圓形遮光物,光線射到其上後就不會再射出。" + }, + "Aperture": { + "title": "光圈", + "description": "一對線段形狀的吸光片,可用對稱方式調整其孔洞的大小。", + "instruction": "拖曳或點擊兩個端點以創建。" + }, + "DiffractionGrating": { + "title": "繞射光柵", + "description": "將光線依波長分割成不同角度的繞射光柵。", + "warning": "注意:繞射光的強度可能不準確。" + }, + "Ruler": { + "title": "直尺", + "description": "指定原點與另一點。" + }, + "Protractor": { + "title": "量角器", + "description": "指定圓心和圓周上一點作為零度位置。刻度單位為度。" + }, + "Detector": { + "title": "探測器", + "description": "測量通過一線段的能量流率(P)、垂直動量流率(F⊥)與水平動量流率(F∥)。單位為任意。" + }, + "TextLabel": { + "title": "文字", + "description": "文字標籤。" + }, + "LineArrow": { + "title": "線段 / 箭頭", + "description": "線段或箭頭。" + }, + "Drawing": { + "title": "繪圖", + "description": "手繪工具。", + "instruction": "拖曳以繪圖。" + }, + "moveView": { + "title": "移動畫面", + "description": "拖曳以移動視窗。(滑鼠右鍵拖曳也有相同的功能)" + }, + "modules": { + "import": "匯入模組...", + "remove": "移除模組" + } + }, + "view": { + "title": "檢視", + "rays": { + "title": "光線", + "description": "畫出光線。當「光線密度」高時,光線呈現連續。" + }, + "extended": { + "title": "延長光線", + "description": "除光線實際路徑外,亦畫出其延長線。橘色、灰色分別表示向後、向前的延長線。", + "simulateColorsNote": "若使用「模擬色彩」,則改以光源顏色顯示並以虛線區分。" + }, + "images": { + "title": "所有像", + "description": "點出像的位置。黃點表示實像,橘點表示虛像,灰點(圖中沒有)表示虛物。注意「光線密度」不夠高時有些像無法正常顯示。", + "simulateColorsNote": "若使用「模擬色彩」,則改以光源顏色顯示並以點的大小區分。" + }, + "observer": { + "title": "觀察者所見", + "description": "模擬從某位置見到的光線與像。藍色圓形為觀察者,與其相交的光線被其「觀察」到。觀察者無法知道光線真正的起始位置,但若其在某處相交,它會認為光線是從該處來的。光線以藍色表示,相交處以黃色(實像)或橘色(虛像)表示。", + "simulateColorsNote": "若使用「模擬色彩」,則改以光源顏色顯示。", + "instruction": "拖曳大藍點以移動觀察者。" + } + }, + "simulateColors": { + "title": "模擬色彩", + "description": "模擬光源的顏色(波長)、混色、遮光物與鏡子的濾光,以及透光物的色散。", + "instruction": "選取物件後可調整這些參數。重疊多條不同波長的光線可用於模擬光譜。", + "warning": "螢幕顯示之顏色僅為粗略近似,且當「光線密度」太高或太低時可能非常不準確。" + }, + "aboutPage": { + "description": "本專案,包括作品集內容,皆採用 [Apache License 2.0](/license) 授權條款,且官方版本位於 [PhyDemo(phydemo.app)](/phydemo)網站(原先於 ricktu288.github.io)。本專案原始碼公開於[此 GitHub Repo](/github),歡迎您[貢獻本專案](/contributing)。若有問題或建議,您可以在 GitHub 上建立 [Issue](/github/issues) 或 [Discussion](/github/discussions)(請使用英文),也可以傳送電子郵件至 [ray-optics@phydemo.app](/email)(可使用中文)。", + "cite": "引用本專案", + "mainAuthors": "主要作者", + "contributors": "貢獻者", + "contributorSorting": "GitHub 貢獻者優先;其餘依時間排序。", + "contributionCategories": { + "code": "程式碼", + "uiDesign": "介面設計", + "gallery": "作品集", + "module": "模組", + "translations": "{{languages}} 翻譯" + } + }, + "languageDropdown": { + "title": "語言:{{language}}", + "translatedFraction": "已翻譯 {{fraction}}" + } +} \ No newline at end of file diff --git a/locales/zh-TW/modules.json b/locales/zh-TW/modules.json new file mode 100644 index 00000000..8ebd7d57 --- /dev/null +++ b/locales/zh-TW/modules.json @@ -0,0 +1,141 @@ +{ + "modulesPage": { + "description": { + "makeNewTools": "「模組」功能透過將本模擬器中現有的工具所建立的物件進行組合、特化或重新參數化,來製作新的工具。", + "appearAsTools": "匯入的模組將顯示為「其他」類別中的工具。請選擇並依照控制點順序點擊空白處(參見「規格」)。", + "embeddedInScene": "匯入的模組將嵌入於場景的資料中,所以當原作者更新時並不會自動更新。" + }, + "import": "匯入", + "imported": "已匯入", + "specification": { + "title": "規格", + "controlPointSequence": "控制點順序", + "parameters": "參數" + }, + "customization": { + "title": "客製化", + "description": "您可直接在本網頁程式中使用內建的 JSON 編輯器製作或客製化模組。請參見[教學](/modules/tutorial)。將匯入的模組客製化僅會影響目前的場景。" + }, + "contribution": { + "title": "貢獻", + "description": "歡迎您貢獻項目至以上的清單。欲貢獻您的模組,請參見[貢獻模組](/contributing/modules)。" + } + }, + "moduleData": { + "FresnelLens": { + "title": "菲涅耳透鏡", + "description": "從半圓形透光物製成的菲涅耳透鏡。[此作品集範例](/gallery/fresnel-lens)的模組化版本。", + "point1": "透鏡的第一個端點", + "point2": "透鏡的第二個端點", + "Nslice": "切片數量", + "refIndex": "透鏡的折射率" + }, + "ContSpectrum": { + "title": "連續光譜光源", + "description": "具有均勻連續光譜的光源,以指定的步長離散化。只在「模擬色彩」模式中運作。", + "point1": "光線的起點", + "point2": "決定光線的方向", + "min": "波長最小值", + "step": "波長的步長", + "max": "波長最大值", + "brightness": "總亮度" + }, + "CircleSource": { + "title": "圓形光源", + "description": "將一系列均勻的180度點光源置於圓周上所形成的光源。", + "point1": "該圓形的圓心", + "r": "該圓形的半徑", + "N": "點光源的數量", + "brightness": "總亮度" + }, + "Chaff": { + "title": "干擾箔", + "description": "矩形的干擾箔,由許多隨機的鏡子組成。[此作品集範例](/gallery/chaff-countermeasure)的模組化版本。", + "point1": "干擾箔的左上角", + "point2": "干擾箔的右下角", + "N": "干擾箔中鏡子的數量", + "L": "鏡子的長度" + }, + "BeamExpander": { + "title": "擴束鏡", + "description": "兩個理想透鏡的組合,使得兩者焦距之和等於兩者間的距離。此組合可以擴大或縮小準直光束的直徑[此作品集範例](/gallery/beam-expanders)的模組化版本。", + "point1": "第一個透鏡的中心點", + "point2": "第二個透鏡的第二個點", + "point3": "決定共同焦點的位置" + }, + "RayRelay": { + "title": "光線中繼", + "description": "一系列相同的理想透鏡,焦距為 \\(f\\),間距為 \\(d\\)。若且唯若 \\(d\\leq 4f\\) 時,可以保證光線軌跡不會發散。[此作品集範例](/gallery/ray-relaying)的模組化版本。", + "point1": "第一個透鏡的第一個端點", + "point2": "第一個透鏡的第二個端點(應與第一點有相同的 \\(x\\))", + "f": "透鏡的焦距", + "d": "透鏡之間的距離", + "N": "透鏡的數量" + }, + "OpticalFiber": { + "title": "光纖", + "description": "指定核心和包層折射率的線狀光纖。", + "point1": "光纖的第一個端點", + "point2": "光纖的第二個端點(應與第一個點有相同的 \\(y\\))", + "X": "核心的厚度", + "Y": "包層的厚度", + "n1": "核心的折射率", + "n2": "包層的折射率" + } + }, + "moduleTutorial": { + "title": "「線光學模擬」模組製作教學", + "opening": { + "description": "本教學將引導您完成建立自訂模組的基本步驟。這個功能可完全在本模擬器網頁程式中實現,而不需要其他的開發環境。", + "moduleIntroduction": "「線光學模擬」的「模組」功能允許將物件以模組化的方式組合在一起,其中可包含自訂參數、自訂控制點與物件陣列。本功能透過將本模擬器中現有的工具所建立的物件進行組合、特化或重新參數化,來製作新的工具,以擴充本模擬器的功能。例如,`CircleSource` 模組(請參見工具->其他->匯入模組)將現有的「點光源(<360°)」工具所建立的一系列點光源沿著一個圓形組合在一起,成為一個「圓形光源」工具,這在模擬器中原本並不存在。 `FresnelLens` 模組則是將「透光物->自訂函數」工具特化,使函數表示菲涅耳透鏡的特定曲線,由切片數參數化,以製作一個特化的「菲涅耳透鏡」工具,這在模擬器中原本也不存在。除了製作新工具外,這個功能還可以使一些光學演示更具互動性。例如,通過拖曳 `BeamExpander` 模組的第三個控制點,可以直接觀察兩個透鏡的共同焦點位置如何影響光束寬度,而無需分別調整兩個透鏡的焦距。", + "compareWithHandle": "注意並非所有的自訂控制點都需要模組。一些簡單的情況可能可以通過「控制桿」功能實現(請參見模擬器右下角的幫助彈出窗口中的「群組、旋轉和縮放物件」部分)。由於製作模組比建立控制桿複雜得多,您應該在考慮製作模組之前檢查您的情況是否可以通過「控制桿」功能實現。比如[這個例子](/gallery/black-cat-becomes-white)展示了一個相對複雜但不必使用模組的自訂控制點(將兩個塑料袋從水中移開)。" + }, + "jsonEditor": { + "title": "內建的 JSON 編輯器", + "currentlyNoVisual": "本程式目前沒有用於建立模組的視覺界面,因此您需要直接編輯場景的 JSON 原始碼。", + "enableJsonEditor": "您可以通過點選網頁介面右上角的「設定」下拉選單,然後勾選「顯示 JSON 編輯器」來啟用內建的 JSON 編輯器。原始碼編輯器會出現在介面的左側,並顯示目前場景的 JSON 原始碼。請確保您有足夠大的螢幕,因為這個功能在行動裝置上效果不佳。", + "updateAccordingly": "當您使用視覺化場景編輯器修改場景時,JSON 編輯器中的原始碼將自動更新,且更改的部分會突出顯示。反之,直接在 JSON 編輯器中編輯原始碼將相應更新場景。如果您不熟悉 JSON 或任何基於文字的資料格式,您可能會希望花一些時間來熟悉它。", + "objsArray": "特別是,當您將一個物件新增到場景中時,它將被新增到 `objs` 陣列中。如果您將某些屬性修改為非預設值,它們將作為該物件的鍵值對出現。", + "inIframesBelow": "注意:如果您在本教學頁面中看不到下面的 iframe 中的 JSON 編輯器,請啟用它並重新載入本頁,因為您需要查看原始碼以了解它的運作方式。" + }, + "basics": { + "title": "模組的基本概念", + "lookAtExample": "讓我們看第一個例子。", + "lookAtJson": "您會看到四段文字。通過查看 JSON 編輯器,您將看到前兩段直接位於頂層的 `objs` 陣列中,但後兩段位於 `modules.ExampleModule.objs` 中。", + "moduleDef": "`module` 是一個字典,其中鍵是模組的名稱(在本例中是 `ExampleModule`),值是該模組的定義。特別是,`modules.ExampleModule.objs` 陣列描述了該模組中的物件(模板),這與描述場景中的物件的頂層 `objs` 陣列不同。", + "putToScene": "要將模組中的物件放到場景中,我們需要一個「模組物件」,它位於頂層 `objs` 陣列中,本例中是 `objs[2]`,其類型是 `ModuleObj`,其 `module` 屬性是模組的名稱。", + "moduleDefNotEditable": "`modules` 字典中的模組定義無法由視覺化場景編輯器編輯。因此,當您點選本例中的後兩段文字時,您只選擇了模組物件,而不是模組中的物件。由於本例中模組定義中的文字座標是絕對座標,因此後兩段文字無法被拖曳。我們將在後面學習到如何使用控制點來使它們可被拖曳。", + "demodulize": "當您選取模組物件時,物件欄上會有一個「取消模組化」按鈕。點選後會將模組物件「展開」為構成此模組的物件,此時 `objs` 將包含所有四段文字。這個操作是不可逆的(除非按「復原」)。", + "createModule": "目前建議製作模組的方式為,首先使用 JSON 編輯器建立一個空的模組,然後使用視覺化場景編輯器新增一些物件,最後使用 JSON 編輯器將這些物件從 `objs` 剪下並貼上到 `modules.ModuleName.objs` 中。" + }, + "parameters": { + "title": "新增參數", + "lookAtExample": "模組中的物件可以由一組參數來定義。讓我們看一個簡單的例子", + "paramsArray": "這裡 `modules.ModuleName.params` 是一個由形如 `\"名稱=起始值:增量:終止值:預設值\"`的字串構成的陣列,定義了變數的名稱和數值滑桿的範圍。當選取模組物件時,滑桿將出現在物件欄上。", + "equationSyntax": "在 `modules.ExampleModule.objs` 陣列中,任何值都可以使用這些參數來表示。在字串中(例如 `TextLabel` 的 `text` 屬性)中,帶有參數的數學式被反引號包圍。對於數值參數(例如 `TextLabel` 的 `fontSize` 屬性),您需要將其改為字串,以便您可以在其中使用反引號格式。因此每條數學式都被一對反引號和一對引號包圍。這些數學式將使用 math.js 來計算([語法](/mathjs/syntax))。請參見該網頁以了解您可以在數學式中使用的語法和函數。", + "valueStorage": "參數的實際值位於模組物件的 `params` 屬性中。這部分與模組定義不同,其可以通過滑桿直接由視覺化場景編輯器編輯。" + }, + "controlPoints": { + "title": "新增控制點", + "lookAtExample": "為了使模組物件可被拖曳,我們需要使用一組控制點來對模組中的物件位置進行參數化。讓我們看一個例子", + "coordinatesOfControlPoints": "這裡 `modules.ModuleName.numPoints` 描述了控制點的數量。控制點座標之符號為 (`x_1`, `y_1`)、(`x_2`, `y_2`) 等等。其用在 `modules.ExampleModule.objs` 中的方式與前一節所述之參數相同。請注意索引從 1 開始。", + "valueStorage": "控制點的實際值位於模組物件的 `controlPoints` 屬性中,其可以直接由視覺化場景編輯器編輯,而非如第一個例子中寫死在模組定義中的座標。每個控制點在場景中顯示為兩個同心的灰色圓形,並且可以被拖曳。若您拖曳模組物件的其他地方(如文字標籤),則所有的控制點會一起移動。", + "createAsTool": "由於我們的模組物件已經可以移動,我們可以很容易地建立多個實例,就像在本模擬器中其他的工具中一樣。模組的名稱顯示在工具->其他選單中,您可以選擇它,然後按兩個點來指定兩個控制點的位置,就可建立此模組的另一個實例。您也可以使用物件欄上的「複製」按鈕。" + }, + "arrayAndConditional": { + "title": "陣列與條件", + "lookAtExample": "使用陣列和條件語法,可以建立更複雜的模組。讓我們看一個例子", + "specialKeys": "在 `modules.ExampleModule.objs` 中,任何陣列中的物件都可以有兩個特殊的鍵: `\"for\"` 和 `\"if\"`。 `\"for\"` 鍵的值是一個描述迴圈變數的字串,格式為 `\"名稱=起始值:增量:終止值\"`,或者是一個包含多個這種格式的字串的陣列,描述多維迴圈。這樣的物件在陣列中根據迴圈變數被複製多次。`\"if\"` 鍵的值是則是一個表示布林值的字串,使得該物件只在布林值為真時才會包含在陣列中。", + "preventInfiniteLoop": "為了防止意外的無窮迴圈,每個 `\"for\"` 迴圈的總迭代次數由模組定義中的 `maxLoopLength` 屬性限制,其預設值為 1000。如果需要,您可以將此屬性設定為更大的值。" + }, + "objsWithEqn": { + "title": "內建自訂數學式功能的物件", + "description": "對於已經具有自訂數學式輸入的物件(例如鏡子 -> 自訂函數),JSON 中的數學式屬性是一個表示 LaTeX 數學式的字串,而不是 math.js 表達式。要在數學式中包含自訂參數,您必須將 LaTeX 數學式視為普通字串,並使用普通字串的模板語法。因此,反引號括起來的部分是 math.js 表達式,而反引號外部的則是 LaTeX 數學式。模組參數只能在 math.js 的部分中使用,而物件內建的自訂函數的自變量(例如 \\(x\\))只能在 LaTeX 的部分中使用。以下例子產生一個形狀為 \\(y=\\cos(2\\pi x+\\phi)\\) 的鏡子,其中 \\(\\phi\\) 為模組參數", + "future": "未來可能會有一種統一的方式來輸入數學式。" + }, + "objsWithShapeParam": { + "title": "內建形狀參數化功能的物件", + "description": "對於已經支援使用不同方式定義其形狀的物件(目前僅有透光物 -> 球面透鏡),有特殊的 JSON 語法可用於在模組定義中用這些方式來定義該物件,即使在頂層 `objs` 陣列中這類的物件總是以形狀來定義。以下是一個例子" + } + } +} \ No newline at end of file diff --git a/locales/zh-TW/simulator.json b/locales/zh-TW/simulator.json new file mode 100644 index 00000000..809563ed --- /dev/null +++ b/locales/zh-TW/simulator.json @@ -0,0 +1,335 @@ +{ + "welcome": { + "title": "歡迎使用「線光學模擬」", + "instruction": "若要加入光學元件,請選擇工具並點擊空白處。\n若要載入範例,[請前往「作品集」頁面](/gallery)。", + "loading": "正在從網址載入場景... 請稍候。" + }, + "common": { + "saveButton": "儲存", + "cancelButton": "取消", + "defaultOption": "預設", + "closeButton": "關閉" + }, + "file": { + "title": "檔案", + "undo": { + "title": "復原" + }, + "redo": { + "title": "重做" + }, + "reset": { + "title": "重設" + }, + "save": { + "title": "儲存" + }, + "open": { + "title": "開啟", + "description": "開啟檔案或背景圖片。背景圖片將從座標原點顯示。(或拖放檔案)" + }, + "export": { + "title": "匯出為PNG/SVG" + }, + "copyLink": { + "title": "複製分享連結", + "description": "複製並前往本場景的專屬網址,以便分享連結(可考慮透過短網址工具)。另見設定->自動同步網址。" + }, + "viewGallery": { + "title": "瀏覽作品集", + "description": "前往「作品集」頁面以載入範例。" + } + }, + "settings": { + "title": "設定", + "more": "更多選項", + "rayDensity": { + "title": "光線密度", + "description": "決定從光束與點光源射出的光線數量。這也會影響到像的偵測與顏色渲染的準確性。" + }, + "layoutAids": { + "title": "排版輔助", + "showGrid": "格線", + "snapToGrid": "對齊格線", + "lockObjs": "鎖定物件" + }, + "gridSize": { + "title": "格線大小" + }, + "observerSize": { + "title": "觀察者大小" + }, + "lengthScale": { + "title": "長度尺度", + "description": "如果將預設的長度單位視為常見的物理單位(例如毫米)時,模擬的物理系統看起來太小或太大,則可以使用此比例來縮放場景中的外觀(例如線寬)。" + }, + "zoom": { + "title": "縮放" + }, + "language": { + "title": "語言" + }, + "autoSyncUrl": { + "title": "自動同步網址", + "description": "啟用時,網址會隨著場景自動更新,而不必持續手動儲存場景。如需設定標題,請用檔案->儲存->重新命名。" + }, + "showJsonEditor": { + "title": "顯示 JSON 編輯器", + "description": "顯示表達場景原始碼的 JSON 編輯器。在建立自訂模組時需要使用(見工具->其他->匯入模組->建立自訂模組)。" + }, + "showStatusBox": { + "title": "顯示狀態方塊", + "description": "顯示狀態方塊,其中包含滑鼠座標,效能資訊,以及被截斷的亮度(光線在內反射的無窮級數中被截斷的總亮度)。" + }, + "showHelpPopups": { + "title": "顯示提示泡泡", + "description": "決定滑鼠移到按鈕上方時是否顯示提示泡泡(須重新載入網頁以套用變更)" + }, + "advancedHelp": "進階說明詳見右下角的說明圖示。" + }, + "objBar": { + "showAdvanced": { + "title": "更多選項…" + }, + "applyToAll": { + "title": "套用全部" + }, + "duplicate": { + "title": "複製" + }, + "delete": { + "title": "刪除" + }, + "unselect": { + "title": "取消選取", + "description": "取消選取此物件(在空白處按滑鼠右鍵也有相同的功能)" + } + }, + "sceneObjs": { + "common": { + "lengthUnitInfo": "本模擬器中的長度單位(除波長外)為一個任意單位。您可將其視為任何物理單位(例如毫米),只要在整個模擬中保持一致。如果單位看起來太小或太大,請調整設定->長度尺度。", + "brightness": "亮度", + "brightnessInfo": { + "rayDensity": "只在「光線密度」夠高時才有作用。", + "rayDensitySlider": "如需改變射出的光線數量,請調整全域性的「光線密度」滑桿。" + }, + "wavelength": "波長", + "emisAngle": "發射角", + "random": "隨機", + "lambert": "朗伯", + "focalLength": "焦距", + "eqnInfo": { + "constants": "支援的常數", + "operators": "支援的運算子", + "functions": "支援的函數" + }, + "imageDetectionWarning": "本工具不支援像的偵測。", + "nonSimulateColorsWarning": "本工具只在「模擬色彩」模式下運作。" + }, + "Beam": { + "imageDetectionWarning": "使用發散或隨機光束時,像的偵測可能無法正常運作。" + }, + "AngleSource": { + "symmetric": "對稱" + }, + "BaseFilter": { + "filter": "濾光", + "bandwidth": "帶寬", + "invert": "反向" + }, + "IdealMirror": { + "cartesianSign": "卡氏符號約定" + }, + "BeamSplitter": { + "transRatio": "透光率" + }, + "BaseGlass": { + "refIndex": "折射率", + "refIndexInfo": { + "relative": "於另一透光物內部時為相對值", + "effective": "如需模擬此物件之(絕對)折射率為 n₁,但其位於折射率為 n₀ 之另一透光物內部的情形,則此處折射率應設為 n₁/n₀ 。在更複雜的組合中,若多個透光物互相重疊,則重疊區域之等效折射率為個別折射率之乘積。" + }, + "cauchyCoeff": "柯西係數" + }, + "SphericalLens": { + "defBy": { + "radiiOfCurvature": "曲率半徑", + "focalDistances": "前/後焦距" + } + }, + "BaseGrinGlass": { + "refIndexFnInfo": { + "constants": "支援的常數", + "operators": "支援的運算子", + "functions": "支援的函數", + "lambda": "如需模擬色散,請用參數 {{lambda}} 代表真空中波長,單位為奈米。", + "diff": "僅支援可微函數。", + "origin": "n(x,y)的原點為絕對座標,不跟隨物件移動。在控制點上點兩下可顯示其絕對座標。", + "accuracy": "如需較精確的模擬,請見「更多選項...」" + }, + "refIndexFnOrigin": "n(x,y)的原點", + "stepSize": "數值求解器步長", + "stepSizeInfo": "用歐拉法求解光線程函方程(eikonal ray equation)的步長 - 更多資訊詳見 'BaseGrinGlass.js' 中的 'step' 函數與原始碼文件。", + "intersectTol": "相交容忍度", + "symbolicBodyMerging": "符號式物體融合", + "symbolicBodyMergingInfo": { + "all": "本選項會套用至所有漸變折射率透光物。", + "impl": "本模擬器目前有兩種光線經過不同漸變折射率介質的實作 - 數值與符號(見 'BaseGrinGlass.js' 中的 'multRefIndex' 與 'devRefIndex' 函數)。", + "implNote": "數值的實作較快,但使用多個漸變折射率介質,且至少有一個介質的折射率沒有在整個平面上有定義時,無法在所有情況下正常運作(取決於具體情況)。相較之下,符號的實作較慢但在這種情況下仍可正常運作。" + } + }, + "CircleGrinGlass": { + "epsInfo": { + "units": "單位 - [長度]^2.", + "functions": "本數值容忍度被用於 'CircleGrinGlass.js' 中的 'isOutsideGlass', 'isInsideGlass' 以及 'isOnBoundary' 函數。" + } + }, + "GrinGlass": { + "epsInfo": { + "units": "單位 - [長度].", + "functions": "本數值容忍度被用於 'GrinGlass.js' 中的 'isOutsideGlass', 'isInsideGlass' 以及 'isOnBoundary' 函數。" + } + }, + "Aperature": { + "diameter": "直徑" + }, + "DiffractionGrating": { + "lineDensity": "線數/{{lengthUnit}}", + "customBrightness": "自訂亮度", + "customBrightnessInfo": "啟用時,繞射光的亮度將由一數值陣列來決定,對應到 m = 0, 1, -1, 2, -2, ...。這些數字為相對於入射光的亮度。陣列中沒有的數值將被設為 0。例如,\"1, 0.5, 0.5\" 表示 m=0 的光線與入射光的亮度相同,m=1 與 m=-1 的光線為入射光的一半,其他光線則被忽略。", + "slitRatio": "狹縫寬度 / 線間距", + "mirrored": "反射" + }, + "Ruler": { + "scaleInterval": "刻度間距" + }, + "Detector": { + "info": { + "P": "P: 能量流率(通量),單位為 B/s(見下文)。", + "Fperp": "F⊥: 垂直動量流率,單位為 (B/s)/c。", + "Fpar": "F∥: 平行動量流率,單位為 (B/s)/c。", + "irradiance": "匯出的 CSV 中的輻照度單位為 (B/s)/L。", + "length": "L 是本模擬器中使用的任意長度單位。", + "B": "B 是輻射通量或光通量的任意單位,對應到「亮度」選項的單位:非朗伯光束為 B/L,點光源為 500B/360°。", + "s": "無因次因子 s 是「設定」->「顯示狀態欄」中顯示的「亮度尺度」,當「光線密度」高於某個閾值時為 1,否則與「光線密度」成正比。", + "truncation": "如果某些光線在內反射的無窮級數中被截斷,則總截斷量將顯示為誤差估計。" + }, + "irradMap": "輻照度圖", + "binSize": "組距", + "exportData": "匯出數據" + }, + "TextLabel": { + "textHere": "在此輸入文字", + "fontSize": "字型大小", + "font": "字型", + "fontStyle": "樣式", + "fontStyles": { + "normal": "正常", + "bold": "粗體", + "italic": "斜體", + "boldItalic": "粗斜體", + "oblique": "傾斜", + "boldOblique": "粗傾斜" + }, + "alignment": "對齊", + "alignments": { + "left": "左", + "center": "中", + "right": "右" + }, + "smallCaps": "小型大寫", + "angle": "角度" + }, + "LineArrow": { + "arrow": "前向箭頭", + "backArrow": "後向箭頭" + }, + "Drawing": { + "finishDrawing": "停止繪圖" + }, + "ModuleObj": { + "module": "模組", + "demodulize": "取消模組化" + }, + "Handle": { + "handle": "控制桿", + "transformation": "變換", + "transformations": { + "translation": "平移", + "xTranslation": "X 平移", + "yTranslation": "Y 平移", + "rotation": "旋轉", + "scaling": "縮放" + } + }, + "CropBox": { + "title": "匯出", + "cropBoxSize": "剪取框大小", + "format": "格式", + "width": "寬度", + "rayCountLimit": "光線數量上限", + "svgWarning": "匯出為SVG:不支援混色與相對折射率低於1的情形。", + "rayCountWarning": "目前場景中的光線數量大於光線數量上限。您可能需要將剪取框選項中的光線數量上限調高。" + } + }, + "saveModal": { + "title": "儲存", + "description": { + "autoSync": "您可使用設定->自動同步網址而不必存成檔案。", + "rename": "按「重新命名」會改變標題但不會存成檔案。", + "contribute": "您可以考慮[貢獻新的項目](/contributing/gallery)到[「作品集」](/gallery)中。" + }, + "fileName": "名稱", + "rename": "重新命名" + }, + "moduleModal": { + "title": "匯入模組", + "makeCustomModules": "製作自訂模組", + "conflict": "場景中已有一個同名但不相同的模組。您可以指定新的名稱,或保留相同名稱以取代原模組。" + }, + "languageModal": { + "title": "語言", + "translatedFraction": "已翻譯", + "helpTranslate": "協助我們翻譯本程式" + }, + "generalWarnings": { + "shareLinkTooLong": "本網址過長,在部分平臺上可能無法正常運作。建議改用「儲存」並分享檔案。", + "autoSyncUrlTooLarge": "本場景過大,無法與網址同步。請自行儲存場景。", + "identicalObjects": "場景中有兩個完全相同的光學元件完全重合。這可能會導致非預期的行為。", + "brightnessInconsistent": "有至少兩個光源的亮度以不一致的比例達到飽和。這可能會導致探測器的讀數與色彩渲染錯誤。請提高光線密度或降低光源亮度。" + }, + "statusBox": { + "rayCount": "光線片段數量", + "totalTruncation": "被截斷的亮度", + "brightnessScale": "亮度尺度", + "timeElapsed": "花費時間", + "forceStopped": "已強制終止。", + "mouseCoordinates": "滑鼠座標" + }, + "footer": { + "processing": "處理中…… 按此處以終止。", + "helpPopup": { + "constrainedDragging": { + "title": "限制拖曳行為", + "description": "拖曳物件時,按住 Shift 可限制於水平或垂直移動;按住 Ctrl 可複製物件。建立線型物件或拖曳其端點時,按住 Shift 可鎖定角度或吸附至 0°、45°、90°;按住 Ctrl 可對於中心點旋轉或縮放。" + }, + "groupRotateScale": { + "title": "群組、旋轉及縮放物件", + "description": "按住 Ctrl,點擊多個控制點(如端點),並點擊空白處可將這些點群組並建立控制桿。拖曳控制桿(或按方向鍵)可平移群組;Shift+拖曳可限制於水平或垂直移動;Ctrl+拖曳可旋轉群組;Ctrl+Shift+拖曳可縮放群組。可移動「+」設定旋轉或縮放中心。點擊控制桿並按 Ctrl+D 可複製群組;按 Delete 可解散群組。" + }, + "editCoordinates": { + "title": "直接編輯座標", + "description": "對控制點(如端點)點兩下或按右鍵,輸入 (x,y) 座標,然後按 Enter。" + }, + "keyboardShortcuts": { + "title": "鍵盤快速鍵", + "description": "當一物件在被選取的狀態(被點擊)時,按方向鍵可移動物件;按 Ctrl+D 可複製物件;按 Delete 可刪除物件。" + }, + "contactUs": { + "title": "聯絡我們", + "description": "建議使用 GitHub 上的 [Discussions](/github/discussions) 或 [Issues](/github/issues) 功能(請使用英文)。若您對 GitHub 不熟,也可發送電子郵件至 [ray-optics@phydemo.app](/email)(可使用中文)。", + "contribute": "也歡迎直接進行貢獻(見[貢獻指南](/contributing))。" + } + } + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 22a88dc2..153573af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,39 +12,46 @@ "@popperjs/core": "2.11.8", "ace-builds": "^1.36.0", "bootstrap": "5.1.3", - "bootstrap3": "npm:bootstrap@^3.3.7", - "canvas": "^2.11.2", "canvas2svg": "github:gliffy/canvas2svg", + "copy-webpack-plugin": "^12.0.2", + "css-loader": "^7.1.2", "evaluatex": "^2.2.0", + "file-loader": "^6.2.0", "file-saver": "^2.0.5", + "html-loader": "^5.1.0", + "html-webpack-plugin": "^5.6.2", + "i18next": "^23.16.5", + "i18next-http-backend": "^2.6.2", "jquery": "^3.7.1", "json-url": "^3.1.0", "mathjs": "^13.2.0", "mathquill": "github:Jutanium/mathquill-webpack", - "seedrandom": "^3.0.5", - "sharp": "^0.33.5", - "tex-math-parser": "^2.0.4" - }, - "devDependencies": { - "copy-webpack-plugin": "^12.0.2", - "css-loader": "^7.1.2", - "file-loader": "^6.2.0", - "html-loader": "^5.1.0", - "html-webpack-plugin": "^5.6.2", - "jsdoc": "^4.0.4", "sass": "^1.80.3", "sass-loader": "^16.0.2", + "seedrandom": "^3.0.5", "style-loader": "^4.0.0", + "tex-math-parser": "^2.0.4", "webpack": "^5.95.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.1.0" + }, + "optionalDependencies": { + "@inquirer/prompts": "^7.1.0", + "bootstrap3": "npm:bootstrap@^3.3.7", + "canvas": "^2.11.2", + "handlebars": "^4.7.8", + "inquirer": "^12.1.0", + "jsdoc": "^4.0.4", + "marked": "^15.0.3", + "sharp": "^0.33.5", + "simple-git": "^3.27.0" } }, "node_modules/@babel/helper-string-parser": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true, + "optional": true, "engines": { "node": ">=6.9.0" } @@ -53,7 +60,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, + "optional": true, "engines": { "node": ">=6.9.0" } @@ -62,7 +69,7 @@ "version": "7.25.6", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", - "dev": true, + "optional": true, "dependencies": { "@babel/types": "^7.25.6" }, @@ -100,7 +107,7 @@ "version": "7.25.6", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", - "dev": true, + "optional": true, "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", @@ -114,7 +121,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -470,11 +476,259 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@inquirer/checkbox": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.0.2.tgz", + "integrity": "sha512-+gznPl8ip8P8HYHYecDtUtdsh1t2jvb+sWCD72GAiZ9m45RqwrLmReDaqdC0umQfamtFXVRoMVJ2/qINKGm9Tg==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.0.2.tgz", + "integrity": "sha512-KJLUHOaKnNCYzwVbryj3TNBxyZIrr56fR5N45v6K9IPrbT6B7DcudBMfylkV1A8PUdJE15mybkEQyp2/ZUpxUA==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.0.tgz", + "integrity": "sha512-I+ETk2AL+yAVbvuKx5AJpQmoaWhpiTFOg/UJb7ZkMAK4blmtG8ATh5ct+T/8xNld0CZG/2UhtkdMwpgvld92XQ==", + "optional": true, + "dependencies": { + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "optional": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/editor": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.1.0.tgz", + "integrity": "sha512-K1gGWsxEqO23tVdp5MT3H799OZ4ER1za7Dlc8F4um0W7lwSv0KGR/YyrUEyimj0g7dXZd8XknM/5QA2/Uy+TbA==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.2.tgz", + "integrity": "sha512-WdgCX1cUtinz+syKyZdJomovULYlKUWZbVYZzhf+ZeeYf4htAQ3jLymoNs3koIAKfZZl3HUBb819ClCBfyznaw==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", + "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.0.2.tgz", + "integrity": "sha512-yCLCraigU085EcdpIVEDgyfGv4vBiE4I+k1qRkc9C5dMjWF42ADMGy1RFU94+eZlz4YlkmFsiyHZy0W1wdhaNg==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.2.tgz", + "integrity": "sha512-MKQhYofdUNk7eqJtz52KvM1dH6R93OMrqHduXCvuefKrsiMjHiMwjc3NZw5Imm2nqY7gWd9xdhYrtcHMJQZUxA==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.2.tgz", + "integrity": "sha512-tQXGSu7IO07gsYlGy3VgXRVsbOWqFBMbqAUrJSc1PDTQQ5Qdm+QVwkP0OC0jnUZ62D19iPgXOMO+tnWG+HhjNQ==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.1.0.tgz", + "integrity": "sha512-5U/XiVRH2pp1X6gpNAjWOglMf38/Ys522ncEHIKT1voRUvSj/DQnR22OVxHnwu5S+rCFaUiPQ57JOtMFQayqYA==", + "optional": true, + "dependencies": { + "@inquirer/checkbox": "^4.0.2", + "@inquirer/confirm": "^5.0.2", + "@inquirer/editor": "^4.1.0", + "@inquirer/expand": "^4.0.2", + "@inquirer/input": "^4.0.2", + "@inquirer/number": "^3.0.2", + "@inquirer/password": "^4.0.2", + "@inquirer/rawlist": "^4.0.2", + "@inquirer/search": "^3.0.2", + "@inquirer/select": "^4.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.2.tgz", + "integrity": "sha512-3XGcskMoVF8H0Dl1S5TSZ3rMPPBWXRcM0VeNVsS4ByWeWjSeb0lPqfnBg6N7T0608I1B2bSVnbi2cwCrmOD1Yw==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/search": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.2.tgz", + "integrity": "sha512-Zv4FC7w4dJ13BOJfKRQCICQfShinGjb1bCEIHxTSnjj2telu3+3RHwHubPG9HyD4aix5s+lyAMEK/wSFD75HLA==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/select": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.0.2.tgz", + "integrity": "sha512-uSWUzaSYAEj0hlzxa1mUB6VqrKaYx0QxGBLZzU4xWFxaSyGaXxsSE4OSOwdU24j0xl8OajgayqFXW0l2bkl2kg==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz", + "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==", + "optional": true, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -488,7 +742,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -497,7 +750,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -506,7 +758,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -515,14 +766,12 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -532,7 +781,7 @@ "version": "0.2.8", "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.8.tgz", "integrity": "sha512-5e+SFVavj1ORKlKaKr2BmTOekmXbelU7dC0cDkQLqag7xfuTPuGMUFx7KWJuv4bYZrTsoL2Z18VVCOKYxzoHcg==", - "dev": true, + "optional": true, "dependencies": { "lodash": "^4.17.21" }, @@ -544,7 +793,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", - "dev": true, "engines": { "node": ">=10.0" }, @@ -560,7 +808,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz", "integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==", - "dev": true, "dependencies": { "@jsonjoy.com/base64": "^1.1.1", "@jsonjoy.com/util": "^1.1.2", @@ -582,7 +829,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", - "dev": true, "engines": { "node": ">=10.0" }, @@ -594,16 +840,54 @@ "tslib": "2" } }, + "node_modules/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "optional": true, + "dependencies": { + "debug": "^4.1.1" + } + }, + "node_modules/@kwsites/file-exists/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@kwsites/file-exists/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "optional": true + }, + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "optional": true + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "dev": true + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "optional": true, "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -624,6 +908,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", + "optional": true, "dependencies": { "glob": "^7.1.3" }, @@ -638,6 +923,7 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "optional": true, "bin": { "semver": "bin/semver.js" }, @@ -649,7 +935,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -662,7 +947,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "engines": { "node": ">= 8" } @@ -671,7 +955,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -684,7 +967,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", - "dev": true, "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", @@ -720,7 +1002,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -740,7 +1021,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -760,7 +1040,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -780,7 +1059,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -800,7 +1078,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -820,7 +1097,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -840,7 +1116,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -860,7 +1135,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -880,7 +1154,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -900,7 +1173,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -920,7 +1192,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -940,7 +1211,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -957,7 +1227,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -978,7 +1247,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, "engines": { "node": ">=18" }, @@ -990,7 +1258,6 @@ "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -1000,7 +1267,6 @@ "version": "3.5.13", "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -1009,7 +1275,6 @@ "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -1018,7 +1283,6 @@ "version": "1.5.4", "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", - "dev": true, "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" @@ -1027,14 +1291,12 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -1046,7 +1308,6 @@ "version": "4.19.5", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", - "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -1057,20 +1318,17 @@ "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" }, "node_modules/@types/http-proxy": { "version": "1.17.15", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -1078,20 +1336,19 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", - "dev": true + "optional": true }, "node_modules/@types/markdown-it": { "version": "14.1.2", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", - "dev": true, + "optional": true, "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" @@ -1101,19 +1358,17 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", - "dev": true + "optional": true }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" }, "node_modules/@types/node": { "version": "22.5.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", - "dev": true, "dependencies": { "undici-types": "~6.19.2" } @@ -1122,7 +1377,6 @@ "version": "1.3.11", "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -1130,26 +1384,22 @@ "node_modules/@types/qs": { "version": "6.9.15", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==" }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -1159,7 +1409,6 @@ "version": "1.9.4", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dev": true, "dependencies": { "@types/express": "*" } @@ -1168,7 +1417,6 @@ "version": "1.15.7", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, "dependencies": { "@types/http-errors": "*", "@types/node": "*", @@ -1179,7 +1427,6 @@ "version": "0.3.36", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -1188,7 +1435,6 @@ "version": "8.5.12", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -1197,7 +1443,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -1206,26 +1451,22 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -1235,14 +1476,12 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -1254,7 +1493,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -1263,7 +1501,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -1271,14 +1508,12 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -1294,7 +1529,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -1307,7 +1541,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -1319,7 +1552,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", @@ -1333,7 +1565,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" @@ -1343,7 +1574,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, "engines": { "node": ">=14.15.0" }, @@ -1356,7 +1586,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, "engines": { "node": ">=14.15.0" }, @@ -1369,7 +1598,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, "engines": { "node": ">=14.15.0" }, @@ -1386,14 +1614,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", @@ -1403,13 +1629,13 @@ "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -1427,7 +1653,6 @@ "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -1439,7 +1664,6 @@ "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true, "peerDependencies": { "acorn": "^8" } @@ -1448,6 +1672,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, "dependencies": { "debug": "4" }, @@ -1459,6 +1684,7 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "optional": true, "dependencies": { "ms": "^2.1.3" }, @@ -1474,13 +1700,13 @@ "node_modules/agent-base/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "optional": true }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1496,7 +1722,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, "dependencies": { "ajv": "^8.0.0" }, @@ -1513,7 +1738,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -1528,23 +1752,35 @@ "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, "peerDependencies": { "ajv": "^6.9.1" } }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "optional": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, "engines": [ "node >= 0.8.0" ], @@ -1578,7 +1814,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1590,13 +1825,15 @@ "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true }, "node_modules/are-we-there-yet": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "deprecated": "This package is no longer supported.", + "optional": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -1609,6 +1846,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "optional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -1622,13 +1860,12 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "optional": true }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -1646,14 +1883,12 @@ "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, "engines": { "node": "*" } @@ -1662,7 +1897,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, "engines": { "node": ">=8" }, @@ -1688,7 +1922,6 @@ "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "dev": true, "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -1712,7 +1945,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -1721,7 +1953,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" @@ -1730,8 +1961,7 @@ "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, "node_modules/bootstrap": { "version": "5.1.3", @@ -1750,6 +1980,7 @@ "version": "3.4.1", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz", "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==", + "optional": true, "engines": { "node": ">=6" } @@ -1778,7 +2009,6 @@ "version": "4.23.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -1809,14 +2039,12 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/bundle-name": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, "dependencies": { "run-applescript": "^7.0.0" }, @@ -1831,7 +2059,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -1840,7 +2067,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -1859,7 +2085,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" @@ -1869,7 +2094,6 @@ "version": "1.0.30001655", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz", "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -1890,6 +2114,7 @@ "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", "hasInstallScript": true, + "optional": true, "dependencies": { "@mapbox/node-pre-gyp": "^1.0.0", "nan": "^2.17.0", @@ -1908,7 +2133,7 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", - "dev": true, + "optional": true, "dependencies": { "lodash": "^4.17.15" }, @@ -1931,11 +2156,16 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "optional": true + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1959,6 +2189,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "optional": true, "engines": { "node": ">=10" } @@ -1967,7 +2198,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, "engines": { "node": ">=6.0" } @@ -1981,7 +2211,6 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, "dependencies": { "source-map": "~0.6.0" }, @@ -1989,11 +2218,19 @@ "node": ">= 10.0" } }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "optional": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -2007,6 +2244,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "optional": true, "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" @@ -2035,6 +2273,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "optional": true, "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -2044,6 +2283,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true, "bin": { "color-support": "bin.js" } @@ -2051,14 +2291,12 @@ "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/complex.js": { "version": "2.1.1", @@ -2076,7 +2314,6 @@ "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, "dependencies": { "mime-db": ">= 1.43.0 < 2" }, @@ -2088,7 +2325,6 @@ "version": "1.7.4", "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, "dependencies": { "accepts": "~1.3.5", "bytes": "3.0.0", @@ -2105,8 +2341,7 @@ "node_modules/compression/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/concat-map": { "version": "0.0.1", @@ -2117,7 +2352,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, "engines": { "node": ">=0.8" } @@ -2125,13 +2359,13 @@ "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, "dependencies": { "safe-buffer": "5.2.1" }, @@ -2143,7 +2377,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -2152,7 +2385,6 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -2160,14 +2392,12 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/copy-webpack-plugin": { "version": "12.0.2", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz", "integrity": "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==", - "dev": true, "dependencies": { "fast-glob": "^3.3.2", "glob-parent": "^6.0.1", @@ -2191,7 +2421,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -2207,7 +2436,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -2219,7 +2447,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -2230,14 +2457,12 @@ "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/copy-webpack-plugin/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -2264,6 +2489,14 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "node_modules/cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, "node_modules/cross-spawn": { "version": "6.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", @@ -2284,7 +2517,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", - "dev": true, "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.33", @@ -2319,7 +2551,6 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -2331,7 +2562,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.0.1", @@ -2347,7 +2577,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, "engines": { "node": ">= 6" }, @@ -2359,7 +2588,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "bin": { "cssesc": "bin/cssesc" }, @@ -2371,7 +2599,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -2385,6 +2612,7 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "optional": true, "dependencies": { "mimic-response": "^2.0.0" }, @@ -2396,7 +2624,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" @@ -2412,7 +2639,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true, "engines": { "node": ">=18" }, @@ -2424,7 +2650,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -2441,7 +2666,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, "engines": { "node": ">=12" }, @@ -2452,13 +2676,13 @@ "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -2467,7 +2691,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -2477,6 +2700,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "optional": true, "engines": { "node": ">=8" } @@ -2484,14 +2708,12 @@ "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" }, @@ -2503,7 +2725,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, "dependencies": { "utila": "~0.4" } @@ -2512,7 +2733,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -2526,7 +2746,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, "funding": [ { "type": "github", @@ -2538,7 +2757,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, "dependencies": { "domelementtype": "^2.2.0" }, @@ -2553,7 +2771,6 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", @@ -2567,7 +2784,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -2584,25 +2800,28 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { "version": "1.5.13", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", - "dev": true + "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==" }, "node_modules/emlapack": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/emlapack/-/emlapack-0.0.3.tgz", "integrity": "sha512-4ul8xbUwsuO0Wpx+QclsPFVWuU2elFWKm2jCO6S6QxVqAbOBjRBj8Zf+3DP7smSPNFMRZe9ysD8k8VkqxfRwFQ==" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "optional": true + }, "node_modules/emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, "engines": { "node": ">= 4" } @@ -2611,7 +2830,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -2620,7 +2838,6 @@ "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -2633,7 +2850,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -2642,7 +2858,6 @@ "version": "7.13.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", - "dev": true, "bin": { "envinfo": "dist/cli.js" }, @@ -2654,7 +2869,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -2666,7 +2880,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -2674,14 +2887,12 @@ "node_modules/es-module-lexer": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, "engines": { "node": ">=6" } @@ -2689,8 +2900,7 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-latex": { "version": "1.2.0", @@ -2701,7 +2911,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, + "optional": true, "engines": { "node": ">=8" } @@ -2710,7 +2920,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -2723,7 +2932,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -2735,7 +2943,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -2744,7 +2951,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -2753,7 +2959,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -2766,23 +2971,21 @@ "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", - "dev": true, + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -2803,7 +3006,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -2818,19 +3021,35 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "optional": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" } }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -2845,20 +3064,17 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-uri": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", - "dev": true + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, "engines": { "node": ">= 4.9.1" } @@ -2867,7 +3083,6 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "dependencies": { "reusify": "^1.0.4" } @@ -2876,7 +3091,6 @@ "version": "0.11.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, "dependencies": { "websocket-driver": ">=0.5.1" }, @@ -2888,7 +3102,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", - "dev": true, "dependencies": { "loader-utils": "^2.0.0", "schema-utils": "^3.0.0" @@ -2924,7 +3137,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "dev": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", @@ -2942,7 +3154,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -2963,7 +3174,6 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, "bin": { "flat": "cli.js" } @@ -2972,7 +3182,6 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, "funding": [ { "type": "individual", @@ -2992,7 +3201,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -3013,7 +3221,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -3036,6 +3243,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "optional": true, "dependencies": { "minipass": "^3.0.0" }, @@ -3047,6 +3255,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, "dependencies": { "yallist": "^4.0.0" }, @@ -3063,7 +3272,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -3077,7 +3285,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3087,6 +3294,7 @@ "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", "deprecated": "This package is no longer supported.", + "optional": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", @@ -3102,29 +3310,10 @@ "node": ">=10" } }, - "node_modules/gauge/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -3163,7 +3352,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -3174,14 +3362,12 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/globby": { "version": "14.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", - "dev": true, "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", "fast-glob": "^3.3.2", @@ -3201,7 +3387,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, "engines": { "node": ">=14.16" }, @@ -3213,7 +3398,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -3229,8 +3413,29 @@ "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } }, "node_modules/has-flag": { "version": "4.0.0", @@ -3244,7 +3449,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -3256,7 +3460,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -3268,7 +3471,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -3279,13 +3481,13 @@ "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -3297,7 +3499,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, "bin": { "he": "bin/he" } @@ -3306,7 +3507,6 @@ "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -3318,7 +3518,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "dev": true, "funding": [ { "type": "github", @@ -3334,7 +3533,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.1.0.tgz", "integrity": "sha512-Jb3xwDbsm0W3qlXrCZwcYqYGnYz55hb6aoKQTlzyZPXsPpi6tHXzAfqalecglMQgNvtEfxrCQPaKT90Irt5XDA==", - "dev": true, "dependencies": { "html-minifier-terser": "^7.2.0", "parse5": "^7.1.2" @@ -3354,7 +3552,6 @@ "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, "engines": { "node": ">=14" } @@ -3363,7 +3560,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -3375,7 +3571,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", - "dev": true, "dependencies": { "camel-case": "^4.1.2", "clean-css": "~5.3.2", @@ -3396,7 +3591,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, "dependencies": { "camel-case": "^4.1.2", "clean-css": "^5.2.2", @@ -3417,7 +3611,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, "engines": { "node": ">= 12" } @@ -3426,7 +3619,6 @@ "version": "5.6.2", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.2.tgz", "integrity": "sha512-q7xp/FO9RGBVoTKNItkdX1jKLscLFkgn/dLVFNYbHVbfHLBk6DYW5nsQ8kCzIWcgKP/kUBocetjvav6lD8YfCQ==", - "dev": true, "dependencies": { "@types/html-minifier-terser": "^6.0.0", "html-minifier-terser": "^6.0.2", @@ -3458,7 +3650,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -3476,14 +3667,12 @@ "node_modules/http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -3498,14 +3687,12 @@ "node_modules/http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" }, "node_modules/http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -3519,7 +3706,6 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", - "dev": true, "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -3543,6 +3729,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -3555,6 +3742,7 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "optional": true, "dependencies": { "ms": "^2.1.3" }, @@ -3570,22 +3758,51 @@ "node_modules/https-proxy-agent/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "optional": true }, "node_modules/hyperdyperid": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", - "dev": true, "engines": { "node": ">=10.18" } }, + "node_modules/i18next": { + "version": "23.16.5", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.5.tgz", + "integrity": "sha512-KTlhE3EP9x6pPTAW7dy0WKIhoCpfOGhRQlO+jttQLgzVaoOjWwBWramu7Pp0i+8wDNduuzXfe3kkVbzrKyrbTA==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/i18next-http-backend": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.6.2.tgz", + "integrity": "sha512-Hp/kd8/VuoxIHmxsknJXjkTYYHzivAyAF15pzliKzk2TiXC25rZCEerb1pUFoxz4IVrG3fCvQSY51/Lu4ECV4A==", + "dependencies": { + "cross-fetch": "4.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -3597,7 +3814,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -3609,7 +3825,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, "engines": { "node": ">= 4" } @@ -3617,14 +3832,12 @@ "node_modules/immutable": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", - "dev": true + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==" }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -3654,11 +3867,31 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/inquirer": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.1.0.tgz", + "integrity": "sha512-3/iexk64jn3EF0tjWYfOJi/DNWtcSSwg4ER67cnopO2xlCTUQjFCTMH9NBNQAMO/+dC3sEvKJtGJsqXnCkSsFg==", + "optional": true, + "dependencies": { + "@inquirer/core": "^10.1.0", + "@inquirer/prompts": "^7.1.0", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2", + "mute-stream": "^2.0.0", + "run-async": "^3.0.0", + "rxjs": "^7.8.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, "node_modules/interpret": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -3667,7 +3900,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "dev": true, "engines": { "node": ">= 10" } @@ -3675,13 +3907,13 @@ "node_modules/is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "optional": true }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -3704,7 +3936,6 @@ "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dev": true, "dependencies": { "hasown": "^2.0.2" }, @@ -3733,7 +3964,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3742,6 +3972,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "optional": true, "engines": { "node": ">=8" } @@ -3750,7 +3981,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -3762,7 +3992,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, "dependencies": { "is-docker": "^3.0.0" }, @@ -3780,7 +4009,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, "bin": { "is-docker": "cli.js" }, @@ -3795,7 +4023,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", - "dev": true, "engines": { "node": ">=16" }, @@ -3815,7 +4042,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, "engines": { "node": ">=10" }, @@ -3827,7 +4053,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "dependencies": { "isobject": "^3.0.1" }, @@ -3860,7 +4085,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3874,7 +4098,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -3888,7 +4111,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -3908,7 +4130,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, + "optional": true, "dependencies": { "xmlcreate": "^2.0.4" } @@ -3917,7 +4139,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz", "integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==", - "dev": true, + "optional": true, "dependencies": { "@babel/parser": "^7.20.15", "@jsdoc/salty": "^0.2.1", @@ -3942,17 +4164,28 @@ "node": ">=12.0.0" } }, + "node_modules/jsdoc/node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "license": "MIT", + "optional": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-url": { "version": "3.1.0", @@ -3972,7 +4205,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -3995,7 +4227,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4004,7 +4235,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", - "dev": true, + "optional": true, "dependencies": { "graceful-fs": "^4.1.9" } @@ -4021,7 +4252,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.1.tgz", "integrity": "sha512-elBx2l/tp9z99X5H/qev8uyDywVh0VXAwEbjk8kJhnc5grOFkGh7aW6q55me9xnYbss261XtnUrysZ+XvGbhQA==", - "dev": true, "dependencies": { "picocolors": "^1.0.0", "shell-quote": "^1.8.1" @@ -4031,7 +4261,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dev": true, + "optional": true, "dependencies": { "uc.micro": "^2.0.0" } @@ -4040,7 +4270,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, "engines": { "node": ">=6.11.5" } @@ -4049,7 +4278,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -4063,7 +4291,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -4074,14 +4301,12 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -4106,6 +4331,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "optional": true, "dependencies": { "semver": "^6.0.0" }, @@ -4120,6 +4346,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "optional": true, "bin": { "semver": "bin/semver.js" } @@ -4128,7 +4355,7 @@ "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "dev": true, + "optional": true, "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -4145,7 +4372,7 @@ "version": "8.6.7", "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", - "dev": true, + "optional": true, "peerDependencies": { "@types/markdown-it": "*", "markdown-it": "*" @@ -4155,7 +4382,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, + "optional": true, "engines": { "node": ">=0.12" }, @@ -4164,15 +4391,16 @@ } }, "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true, + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.3.tgz", + "integrity": "sha512-Ai0cepvl2NHnTcO9jYDtcOEtVBNVYR31XnEA3BndO7f5As1wzpcOceSUM8FDkNLJNIODcLpDTWay/qQhqbuMvg==", + "license": "MIT", + "optional": true, "bin": { "marked": "bin/marked.js" }, "engines": { - "node": ">= 12" + "node": ">= 18" } }, "node_modules/mathjs": { @@ -4218,13 +4446,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true + "optional": true }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -4233,7 +4460,6 @@ "version": "4.11.1", "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", - "dev": true, "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", "@jsonjoy.com/util": "^1.3.0", @@ -4252,7 +4478,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -4260,14 +4485,12 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "engines": { "node": ">= 8" } @@ -4276,7 +4499,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -4297,7 +4519,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, "bin": { "mime": "cli.js" }, @@ -4309,7 +4530,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -4318,7 +4538,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -4330,6 +4549,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "optional": true, "engines": { "node": ">=8" }, @@ -4340,8 +4560,7 @@ "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "node_modules/minimatch": { "version": "3.1.2", @@ -4366,6 +4585,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "optional": true, "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -4378,6 +4598,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, "dependencies": { "yallist": "^4.0.0" }, @@ -4389,6 +4610,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -4399,8 +4621,7 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/msgpack5": { "version": "4.5.1", @@ -4417,7 +4638,6 @@ "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" @@ -4426,22 +4646,32 @@ "multicast-dns": "cli.js" } }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "optional": true, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/nan": { "version": "2.22.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", - "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==" + "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "optional": true }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -4453,7 +4683,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -4461,8 +4690,7 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/next-pow-2": { "version": "1.0.0", @@ -4478,7 +4706,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" @@ -4487,8 +4714,7 @@ "node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "dev": true + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" }, "node_modules/node-fetch": { "version": "2.7.0", @@ -4513,7 +4739,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, "engines": { "node": ">= 6.13.0" } @@ -4532,13 +4757,13 @@ "node_modules/node-releases": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "optional": true, "dependencies": { "abbrev": "1" }, @@ -4553,7 +4778,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4563,6 +4787,7 @@ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "deprecated": "This package is no longer supported.", + "optional": true, "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", @@ -4574,7 +4799,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, "dependencies": { "boolbase": "^1.0.0" }, @@ -4586,6 +4810,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "optional": true, "engines": { "node": ">=0.10.0" } @@ -4594,7 +4819,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -4605,14 +4829,12 @@ "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -4624,7 +4846,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -4664,7 +4885,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -4679,7 +4899,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -4691,7 +4910,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", - "dev": true, "dependencies": { "@types/retry": "0.12.2", "is-network-error": "^1.0.0", @@ -4708,7 +4926,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -4717,7 +4934,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -4727,7 +4943,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, "dependencies": { "entities": "^4.4.0" }, @@ -4739,7 +4954,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -4751,7 +4965,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -4760,7 +4973,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -4798,7 +5010,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -4822,20 +5033,18 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", - "dev": true + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/path-type": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, "engines": { "node": ">=12" }, @@ -4846,8 +5055,7 @@ "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -4864,7 +5072,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, "dependencies": { "find-up": "^4.0.0" }, @@ -4876,7 +5083,6 @@ "version": "8.4.42", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.42.tgz", "integrity": "sha512-hywKUQB9Ra4dR1mGhldy5Aj1X3MWDSIA1cEi+Uy0CjheLvP6Ual5RlwMCh8i/X121yEDLDIKBsrCQ8ba3FDMfQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -4904,7 +5110,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -4916,7 +5121,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^6.0.2", @@ -4933,7 +5137,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.4" }, @@ -4948,7 +5151,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, "dependencies": { "icss-utils": "^5.0.0" }, @@ -4963,7 +5165,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -4975,14 +5176,12 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, "dependencies": { "lodash": "^4.17.20", "renderkid": "^3.0.0" @@ -4997,7 +5196,6 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -5010,7 +5208,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, "engines": { "node": ">= 0.10" } @@ -5019,7 +5216,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "engines": { "node": ">=6" } @@ -5028,7 +5224,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, + "optional": true, "engines": { "node": ">=6" } @@ -5037,7 +5233,6 @@ "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, "dependencies": { "side-channel": "^1.0.6" }, @@ -5052,7 +5247,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -5072,7 +5266,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -5081,7 +5274,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -5090,7 +5282,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -5105,7 +5296,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -5133,7 +5323,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -5145,7 +5334,6 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, "dependencies": { "resolve": "^1.20.0" }, @@ -5162,7 +5350,6 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, "engines": { "node": ">= 0.10" } @@ -5171,7 +5358,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, "dependencies": { "css-select": "^4.1.3", "dom-converter": "^0.2.0", @@ -5184,7 +5370,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -5192,14 +5377,13 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/requizzle": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", - "dev": true, + "optional": true, "dependencies": { "lodash": "^4.17.21" } @@ -5208,7 +5392,6 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -5225,7 +5408,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, "dependencies": { "resolve-from": "^5.0.0" }, @@ -5237,7 +5419,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, "engines": { "node": ">=8" } @@ -5246,7 +5427,6 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, "engines": { "node": ">= 4" } @@ -5255,7 +5435,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -5277,7 +5456,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", - "dev": true, "engines": { "node": ">=18" }, @@ -5285,11 +5463,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "optional": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -5308,6 +5494,15 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "optional": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -5330,14 +5525,12 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass": { "version": "1.80.3", "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.3.tgz", "integrity": "sha512-ptDWyVmDMVielpz/oWy3YP3nfs7LpJTHIJZboMVs8GEC9eUmtZTZhMHlTW98wY4aEorDfjN38+Wr/XjskFWcfA==", - "dev": true, "dependencies": { "@parcel/watcher": "^2.4.1", "chokidar": "^4.0.0", @@ -5355,7 +5548,6 @@ "version": "16.0.2", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.2.tgz", "integrity": "sha512-Ll6iXZ1EYwYT19SqW4mSBb76vSSi8JgzElmzIerhEGgzB5hRjDQIWsPmuk1UrAXkR16KJHqVY0eH+5/uw9Tmfw==", - "dev": true, "dependencies": { "neo-async": "^2.6.2" }, @@ -5395,7 +5587,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -5410,7 +5601,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, "engines": { "node": ">= 14.16.0" }, @@ -5423,7 +5613,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -5445,14 +5634,12 @@ "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" }, "node_modules/selfsigned": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, "dependencies": { "@types/node-forge": "^1.3.0", "node-forge": "^1" @@ -5473,7 +5660,6 @@ "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "dev": true, "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -5497,7 +5683,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -5505,14 +5690,12 @@ "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -5521,7 +5704,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", @@ -5539,7 +5721,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -5548,7 +5729,6 @@ "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -5562,20 +5742,17 @@ "node_modules/serve-index/node_modules/inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" }, "node_modules/serve-index/node_modules/setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "node_modules/serve-index/node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -5584,7 +5761,6 @@ "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dev": true, "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", @@ -5598,13 +5774,13 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "optional": true }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -5620,14 +5796,12 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, "dependencies": { "kind-of": "^6.0.2" }, @@ -5640,6 +5814,7 @@ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "hasInstallScript": true, + "optional": true, "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", @@ -5677,6 +5852,7 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "optional": true, "bin": { "semver": "bin/semver.js" }, @@ -5707,7 +5883,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5716,7 +5891,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -5733,7 +5907,8 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "optional": true }, "node_modules/simple-concat": { "version": "1.0.1", @@ -5752,22 +5927,63 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "optional": true }, "node_modules/simple-get": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "optional": true, "dependencies": { "decompress-response": "^4.2.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, + "node_modules/simple-git": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.27.0.tgz", + "integrity": "sha512-ivHoFS9Yi9GY49ogc6/YAi3Fl9ROnF4VyubNylgCkA+RVqLaKWnDSzXOVzya8csELIaWaYNutsEuAhZrtOjozA==", + "optional": true, + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.3.5" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, + "node_modules/simple-git/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/simple-git/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "optional": true + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "optional": true, "dependencies": { "is-arrayish": "^0.3.1" } @@ -5784,7 +6000,6 @@ "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", @@ -5795,7 +6010,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -5804,7 +6018,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -5813,7 +6026,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -5823,7 +6035,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", @@ -5839,7 +6050,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -5853,7 +6063,6 @@ "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -5869,14 +6078,12 @@ "node_modules/spdy-transport/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/spdy-transport/node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -5890,7 +6097,6 @@ "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -5906,14 +6112,12 @@ "node_modules/spdy/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -5931,6 +6135,20 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -5946,7 +6164,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, + "optional": true, "engines": { "node": ">=8" }, @@ -5958,7 +6176,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", - "dev": true, "engines": { "node": ">= 18.12.0" }, @@ -5985,7 +6202,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -5997,7 +6213,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -6006,6 +6221,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "optional": true, "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -6022,6 +6238,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "optional": true, "engines": { "node": ">=8" } @@ -6030,7 +6247,6 @@ "version": "5.31.6", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", - "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -6048,7 +6264,6 @@ "version": "5.3.10", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", @@ -6123,7 +6338,6 @@ "version": "1.21.0", "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", - "dev": true, "engines": { "node": ">=10.18" }, @@ -6134,8 +6348,7 @@ "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" }, "node_modules/tiny-emitter": { "version": "2.1.0", @@ -6157,7 +6370,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, + "optional": true, "engines": { "node": ">=4" } @@ -6177,7 +6390,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, "engines": { "node": ">=0.6" } @@ -6191,7 +6403,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", - "dev": true, "engines": { "node": ">=10.0" }, @@ -6206,14 +6417,24 @@ "node_modules/tslib": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "devOptional": true + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -6234,25 +6455,36 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true + "optional": true + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } }, "node_modules/underscore": { "version": "1.13.7", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", - "dev": true + "optional": true }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, "node_modules/unicorn-magic": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true, "engines": { "node": ">=18" }, @@ -6272,7 +6504,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -6281,7 +6512,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -6311,7 +6541,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -6329,14 +6558,12 @@ "node_modules/utila": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, "engines": { "node": ">= 0.4.0" } @@ -6345,7 +6572,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -6354,7 +6580,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -6363,7 +6588,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -6376,7 +6600,6 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, "dependencies": { "minimalistic-assert": "^1.0.0" } @@ -6390,7 +6613,6 @@ "version": "5.95.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", - "dev": true, "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -6436,7 +6658,6 @@ "version": "5.1.4", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", @@ -6481,7 +6702,6 @@ "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, "engines": { "node": ">=14" } @@ -6490,7 +6710,6 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -6505,7 +6724,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -6514,7 +6732,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -6526,7 +6743,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -6535,7 +6751,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -6550,7 +6765,6 @@ "version": "7.4.2", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", - "dev": true, "dependencies": { "colorette": "^2.0.10", "memfs": "^4.6.0", @@ -6579,7 +6793,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -6595,7 +6808,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -6606,14 +6818,12 @@ "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/webpack-dev-middleware/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -6632,7 +6842,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.1.0.tgz", "integrity": "sha512-aQpaN81X6tXie1FoOB7xlMfCsN19pSvRAeYUHOdFWOlhpQ/LlbfTqYwwmEDFV0h8GGuqmCmKmT+pxcUV/Nt2gQ==", - "dev": true, "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", @@ -6689,7 +6898,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -6705,7 +6913,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -6717,7 +6924,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, "dependencies": { "is-inside-container": "^1.0.0" }, @@ -6731,14 +6937,12 @@ "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/webpack-dev-server/node_modules/open": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", - "dev": true, "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", @@ -6756,7 +6960,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -6775,7 +6978,6 @@ "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "dev": true, "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", @@ -6789,7 +6991,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -6798,7 +6999,6 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, "dependencies": { "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", @@ -6812,7 +7012,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -6841,34 +7040,37 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "node_modules/wide-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" }, - "node_modules/wide-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT", + "optional": true + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "optional": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -6878,7 +7080,6 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, "engines": { "node": ">=10.0.0" }, @@ -6899,12 +7100,13 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true + "optional": true }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true }, "node_modules/yaml": { "version": "1.10.2", @@ -6913,6 +7115,18 @@ "engines": { "node": ">= 6" } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index ad66f654..eee95ebe 100644 --- a/package.json +++ b/package.json @@ -10,43 +10,52 @@ "@popperjs/core": "2.11.8", "ace-builds": "^1.36.0", "bootstrap": "5.1.3", - "bootstrap3": "npm:bootstrap@^3.3.7", - "canvas": "^2.11.2", "canvas2svg": "github:gliffy/canvas2svg", + "copy-webpack-plugin": "^12.0.2", + "css-loader": "^7.1.2", "evaluatex": "^2.2.0", + "file-loader": "^6.2.0", "file-saver": "^2.0.5", + "html-loader": "^5.1.0", + "html-webpack-plugin": "^5.6.2", + "i18next": "^23.16.5", + "i18next-http-backend": "^2.6.2", "jquery": "^3.7.1", "json-url": "^3.1.0", "mathjs": "^13.2.0", "mathquill": "github:Jutanium/mathquill-webpack", - "seedrandom": "^3.0.5", - "sharp": "^0.33.5", - "tex-math-parser": "^2.0.4" - }, - "devDependencies": { - "copy-webpack-plugin": "^12.0.2", - "css-loader": "^7.1.2", - "file-loader": "^6.2.0", - "html-loader": "^5.1.0", - "html-webpack-plugin": "^5.6.2", - "jsdoc": "^4.0.4", "sass": "^1.80.3", "sass-loader": "^16.0.2", + "seedrandom": "^3.0.5", "style-loader": "^4.0.0", + "tex-math-parser": "^2.0.4", "webpack": "^5.95.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.1.0" }, + "optionalDependencies": { + "@inquirer/prompts": "^7.1.0", + "bootstrap3": "npm:bootstrap@^3.3.7", + "canvas": "^2.11.2", + "handlebars": "^4.7.8", + "marked": "^15.0.3", + "inquirer": "^12.1.0", + "jsdoc": "^4.0.4", + "sharp": "^0.33.5", + "simple-git": "^3.27.0" + }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "sync-translations": "node ./scripts/syncTranslations.js", - "build-translations": "node ./scripts/buildTranslations.js", - "build-webpages": "node ./scripts/buildWebpages.js", + "build-webpages": "node ./scripts/buildWebpages.mjs", + "build-scenes": "node ./scripts/buildScenes.mjs", + "build-node": "webpack --config webpack.node.config.mjs", + "build-images": "node ./scripts/buildImages.mjs", "build-simulator": "webpack --mode=production", "build-docs": "jsdoc -c jsdoc.json", - "build-node": "webpack --config webpack.node.config.js", - "build-images": "node ./scripts/buildImages.js", "start": "webpack serve --open simulator/ --mode=development", - "build": "npm run build-translations && npm run build-webpages && npm run build-node && npm run build-images && npm run build-simulator && npm run build-docs" + "build": "npm run build-webpages && npm run build-scenes && npm run build-node && npm run build-images && npm run build-simulator && npm run build-docs", + "add-to-gallery": "node ./scripts/addToGallery.mjs", + "add-to-modules": "node ./scripts/addToModules.mjs", + "sort-translations": "node ./scripts/sortTranslations.mjs" } } diff --git a/scripts/addToGallery.mjs b/scripts/addToGallery.mjs new file mode 100644 index 00000000..e8abba7e --- /dev/null +++ b/scripts/addToGallery.mjs @@ -0,0 +1,402 @@ +import inquirer from 'inquirer'; +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import jsonUrl from 'json-url'; + + +// Convert import.meta.url to a file path and determine the directory +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Load the gallery data. +const galleryList = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/galleryList.json'), 'utf8')); +const categoryIDs = galleryList.map((category) => category.id); + +// List all existing scenes IDs, which are the file name of the json files in the /data/galleryScenes directory. +const sceneFiles = fs.readdirSync(path.join(__dirname, '../data/galleryScenes')); +const sceneIDs = sceneFiles.filter((file) => file.endsWith('.json')).map((file) => file.replace('.json', '')); + +// Create a dictionary converting the scene IDs to the camelCase format. +const sceneIDToCamelCase = {}; +sceneIDs.forEach((id) => { + sceneIDToCamelCase[id] = id.toLowerCase().replace(/-([a-z])/g, (g) => g[1].toUpperCase()); +}); + +// Load the English data of the gallery. +const galleryLocaleData = JSON.parse(fs.readFileSync(path.join(__dirname, '../locales/en/gallery.json'), 'utf8')); +const galleryStrings = galleryLocaleData.galleryData; +const galleryCagegories = galleryLocaleData.galleryPage.categories; + +// Create a dictionary converting the category IDs to the camelCase format. +const categoryIDToCamelCase = {}; +categoryIDs.forEach((id) => { + categoryIDToCamelCase[id] = id.toLowerCase().replace(/-([a-z])/g, (g) => g[1].toUpperCase()); +}); + +// Create a dictionary mapping the IDs to the English titles. +const sceneIDToTitle = {}; +sceneIDs.forEach((id) => { + sceneIDToTitle[id] = galleryStrings[sceneIDToCamelCase[id]].title; +}); + +// Create a dictionary mapping the category IDs to the English titles. +const categoryIDToTitle = {}; +categoryIDs.forEach((id) => { + categoryIDToTitle[id] = galleryCagegories[categoryIDToCamelCase[id]]; +}); + +// Create an object mapping all string keys to the English values, with reserved keys mapping to null. +const reservedKeys = ["title", "description"]; +const stringKeys = {}; +reservedKeys.forEach((key) => { + stringKeys[key] = null; +}); +sceneIDs.forEach((id) => { + const scene = galleryStrings[sceneIDToCamelCase[id]]; + for (const key in scene) { + if (!reservedKeys.includes(key)) { + stringKeys[key] = {string: scene[key], source: id}; + } + } +}); + +// Add the common keys to stringKeys. +for (const key in galleryStrings.common) { + stringKeys[key] = {string: galleryStrings.common[key], source: 'common'}; +} + +// Prompt the requirement to the user. +console.log('Welcome to the gallery item creation tool.'); +console.log(''); +console.log('Please read the requirements for the new gallery item:'); +console.log('1. All translatable text must be in English. If you want to provide a version in some other language, you can do this with the translation tool after the scene is added.'); +console.log('2. The scene for the Gallery webpage should contain two CropBox objects, one is rectangular (for the preview in the item page), and the other is square (for the thumbnail in the Gallery list). To create a CropBox object, click File -> Export PNG/SVG (but no need to actually export the image). To create the second CropBox, click Duplicate in the object bar while the first CropBox is selected. To make it square, set the two coordinates of the crop box to the same value in the object bar. Do not adjust image format and resolution.'); +console.log('3. If your scene involves infinite numbers of rays (e.g. repeated reflection in a cavity), you should click "More options..." and set a suitable "Ray count limit" for both CropBox objects to avoid infinite loops.') +console.log('4. If the scene is not for the Gallery webpage (e.g. an example scene to be embedded in the documentation), you can skip the CropBox objects.'); +console.log('5. All translatable text in the scene must have an appropriate aligment, as the length of the text may vary in different languages but the coordinates of the TextLabel will not change with the language. To set the alignment, select the text label, click "More options..." in the object bar. You should avoid placing the text labels at some length-sensitive positions, so if the text becomes too long in some languages, it will not overlap with other objects or go out of some CropBox.'); +console.log('6. When the scene is ready, click File -> Copy Sharable Link. The shared URL will be used to provide the scene data. Ignore the warning if the URL is too long.'); +console.log(''); + +// Prompt the user for the scene data (the shared URL). +const sceneURLInput = await inquirer.prompt({ + type: 'editor', + name: 'sceneURL', + message: "The shared URL of the scene:", +}); +console.log(''); + +// Decode the hash part of the URL (LZMA compressed JSON) using json-url. +const sceneData = await jsonUrl('lzma').decompress(sceneURLInput.sceneURL.split('#')[1]); + +// Ensure that the scene data has a title. +let title = sceneData.name; +if (!title) { + const titlePrompt = await inquirer.prompt({ + type: 'input', + name: 'title', + message: "The scene does not have a title. Please enter the title of the scene:", + validate: (input) => input.trim() !== '' || 'The title cannot be empty.', + }); + title = titlePrompt.title.trim(); +} else { + console.log(`Title: ${title}`); +} + +// The title is not stored in the extracted scene data. +delete sceneData.name; + +// Ensure that the scene data contains two CropBox objects, one is square (for thumbnail) and the other is rectangular (for preview). +let cropBoxPreview = null; +let cropBoxThumbnail = null; +for (const obj of sceneData.objs) { + if (obj.type === 'CropBox') { + if (Math.abs((obj.p4.x - obj.p1.x) - (obj.p4.y - obj.p1.y)) < 1e-6) { + cropBoxThumbnail = obj; + } else { + cropBoxPreview = obj; + } + } +} + +let forGalleryPage = true; +if (!cropBoxPreview || !cropBoxThumbnail) { + const confirmPrompt = await inquirer.prompt({ + type: 'confirm', + name: 'notForGallery', + message: 'Some CropBox objects are missing. Do you want to proceed without the CropBox objects? (The scene will not be added to the Gallery webpage.)', + default: false, + }); + + if (!confirmPrompt.notForGallery) { + console.log('Please add the CropBox objects to the scene and try again.'); + process.exit(1); + } + forGalleryPage = false +} + +// Convert the title into a kebab-case ID. +let id = title.toLowerCase().replace(/[^a-z\s]/g, '').replace(/\s+/g, '-'); +const MAX_ID_LENGTH = 55; +if (id.length > MAX_ID_LENGTH) { + id = id.substring(0, MAX_ID_LENGTH); +} + +// Prompt the user for the id of the scene, with the above title as a default. The length of the ID must not exceed 55 characters. +console.log('Please provide the ID of the scene, which is used in the URL of the scene page. The ID is usually the title (or some shortened form) in the kebab-case format. It cannot be changed after the scene is published.'); +let idInput = await inquirer.prompt({ + type: 'text', + name: 'id', + message: "The ID of the scene:", + default: id, + validate: (input) => { + if (input.length > MAX_ID_LENGTH) { + return `The ID must not exceed ${MAX_ID_LENGTH} characters.`; + } + if (sceneIDs.includes(input)) { + return 'The ID is already in use.'; + } + return true; + } +}); +console.log(''); + +id = idInput.id; + +const newSceneIdCamelCase = id.replace(/-([a-z])/g, (g) => g[1].toUpperCase()); +sceneIDToCamelCase[id] = newSceneIdCamelCase; +sceneIDToTitle[id] = title; + +const newSceneStrings = {}; +newSceneStrings.title = title; + +if (forGalleryPage) { + // Prompt the user for the description of the scene, which can be multi-line. + console.log('Please provide the description of the scene in markdown format. To include inline LaTeX equations, use the \\( and \\) delimiters. To include displayed LaTeX equation, use \\begin{equation} and \\end{equaion}. The equation will be rendered using MathJax. To include a link to another scene in the gallery, use the format [title](/gallery/SCENE_ID).'); + const descriptionPrompt = await inquirer.prompt({ + type: 'editor', + name: 'description', + message: "The description of the scene:", + }); + + const description = descriptionPrompt.description.trim(); + newSceneStrings.description = description; + console.log(''); + console.log(description); + console.log(''); +} + +// Extract the TextLabel objects from the scene data recursively. Store the references to an array. +const textLabels = []; +function extractTextLabels(obj) { + if (obj.type === 'TextLabel') { + textLabels.push(obj); + } else { + // Loop through all the properties of the object. + for (const key in obj) { + if (typeof obj[key] === 'object') { + extractTextLabels(obj[key]); + } + } + } +} +extractTextLabels(sceneData); + +if (textLabels.length > 0) { + const MAX_PREVIEW_CHARACTERS = 50; + + // Collect all texts. Truncate the text if too long. + const textPreviews = textLabels.map((textLabel) => { + const text = textLabel.text; + const firstLine = text.split('\n')[0]; + const truncated = firstLine.length > MAX_PREVIEW_CHARACTERS ? firstLine.substring(0, MAX_PREVIEW_CHARACTERS) + '...' : firstLine; + return text.includes('\n') || firstLine.length > MAX_PREVIEW_CHARACTERS ? truncated + '...' : truncated; + }); + + // Ask the user for each text if it is translatable. Use one prompt including all texts. + console.log('Please select which texts in the scene are translatable to other languages. If a text contains at least one English word, it should be marked as translatable. However, if the only words are part of a variable name of some module (e.g. "N_slice=20"), it should not be marked as translatable.'); + const translatablePrompt = await inquirer.prompt({ + type: 'checkbox', + name: 'translatable', + message: "Which texts are translatable?", + choices: textPreviews.map((text, index) => ({ name: text, value: index, checked: text.length >= 3 })), + }); + console.log(''); + + const translatableIndexes = translatablePrompt.translatable; + + // Ask if any of those translatable texts should be stored in the common gallery strings. + console.log('Please select which translatable texts are common strings. Common strings are shared among multiple scenes. Please mark the text as common only if it is truly general and does not depend on the context of the scene. The current convension is to only mark long warning-type texts as common strings.'); + const commonStringsPrompt = await inquirer.prompt({ + type: 'checkbox', + name: 'commonStrings', + message: "Which translatable texts are common strings?", + choices: translatableIndexes.map(index => ({ + name: textPreviews[index], + value: index, + checked: false + })), + }); + console.log(''); + + const commonStringsIndexes = commonStringsPrompt.commonStrings; + const nonCommonStringsIndexes = translatableIndexes.filter(index => !commonStringsIndexes.includes(index)); + + let hasMultipleInstances = false; + for (const index of translatableIndexes) { + const textLabel = textLabels[index]; + const text = textLabel.text; + + // Generate a default key from the letters and digits of the English version with all lowercase and no spaces, clipped to 20 characters. + let tempKey = text.replace(/[^a-zA-Z0-9]/g, '').toLowerCase().substring(0, 20); + + // If the key is empty or starts with a digit, prepend a letter. + if (tempKey.length === 0 || tempKey[0].match(/[0-9]/)) { + tempKey = 't' + tempKey; + } + + // If the key is already in use, append a number to it. + let number = 1; + let newKey = tempKey; + while (Object.keys(stringKeys).includes(newKey)) { + newKey = tempKey + number; + number++; + } + + // Search if the text appears in some existing items. List all instances. + const instances = []; + for (const key in stringKeys) { + if (stringKeys[key] && stringKeys[key].string === text) { + instances.push(key); + } + } + + let key = newKey; + + // Ask the user if the text should be linked to an existing string key. + if (instances.length > 0) { + if (!hasMultipleInstances) { + hasMultipleInstances = true; + console.log('Some translatable texts are identical to existing strings. Please select which string key should be used for each text. If the identical string is from another scene (i.e. not the current scene or a common string), you should only link it if the two scenes are parallel in content. Otherwise, create a new key even if the strings are identical.'); + } + + const keyPrompt = await inquirer.prompt({ + type: 'list', + name: 'key', + message: `The text "${textPreviews[index]}" appears in the following items. Which one should be used?`, + choices: [ + { name: 'Create a new key', value: newKey }, + ...instances.map(instance => ({ + name: `{{${instance}}} in "${sceneIDToTitle[stringKeys[instance].source] || 'common'}"`, + value: instance + })) + ], + }); + console.log(''); + key = keyPrompt.key; + } + + // Replace the text in the scene data with {{key}}. + textLabel.text = `{{${key}}}`; + + // Store the text in the new scene strings. + if (key === newKey) { + if (commonStringsIndexes.includes(index)) { + stringKeys[key] = { string: text, source: 'common' }; + galleryStrings.common[key] = text; + } else { + stringKeys[key] = { string: text, source: id }; + newSceneStrings[key] = text; + } + } + } +} + +// Ask if the scene contains a background image. +console.log('If your scene contains a background image, the image file must be provided manually in /data/galleryScenes directory. The image file must be in the PNG format and the file name must be the ID of the scene followed by "-background.png".'); +const backgroundImagePrompt = await inquirer.prompt({ + type: 'confirm', + name: 'backgroundImage', + message: "Does the scene contain a background image?", + default: false, +}); +console.log(''); + +if (backgroundImagePrompt.backgroundImage) { + sceneData.backgroundImage = `${id}-background.png`; +} + +if (forGalleryPage) { + // Ask the user for the category of the scene. + console.log('Please select the category of the scene. By the current convention, if the simulation is about a general principle or commonly used optical instrument, it is placed in the category corresponding in the most important optical principle. If there is no specific optical principle, the most important principle is not listed, or if the simulation is about an application of optics, then it should be placed in the "Miscellaneous" category.'); + const categoryPrompt = await inquirer.prompt({ + type: 'list', + name: 'category', + message: "The category of the scene:", + choices: categoryIDs.map((id) => ({ name: categoryIDToTitle[id], value: id })), + }); + console.log(''); + + const category = categoryPrompt.category; + + // Ask the user for the position of the scene in the category. The position is stored as the id of the scene before the new scene. One should not put the new scene in the first position. + console.log('Please select the position of the scene in the category. The new scene will be placed after the selected scene. If there are existing scenes in the category related to the new scene, you can place the new scene after them. Otherwise, it is recommended to place the new scene at the end of the category.'); + const categoryScenes = galleryList.find((category1) => category1.id === category).content; + const categorySceneTitles = categoryScenes.map((scene) => sceneIDToTitle[scene.id]); + const categoryScenePrompt = await inquirer.prompt({ + type: 'list', + name: 'position', + message: "The position of the scene in the category:", + choices: categorySceneTitles.map((title, index) => ({ name: title, value: index })), + loop: false, + }); + console.log(''); + + const position = categoryScenePrompt.position; + const positionID = categoryScenes[position].id; + const positionCamelCase = sceneIDToCamelCase[positionID]; + + // Ask the name of the contributors. + console.log('Please provide the name of the contributor(s) of the scene. The name will be displayed in the scene page as well as the About page. The name can be a pseudonym or a real name, but must be in Latin characters. If the contributor has contributed before, please use the same name. If the author has a GitHub account, it is recommended to use the GitHub username or the "name" field in the GitHub profile if it is in Latin characters. If the scene has multiple contributors, separate the names by semicolons, and should sort by the chronological order of the contributions.') + const contributorsPrompt = await inquirer.prompt({ + type: 'text', + name: 'contributors', + message: "The name of the contributor(s):", + }); + console.log(''); + + const contributors = contributorsPrompt.contributors; + const contributorList = contributors.split(';').map((name) => name.trim()); + + // Insert the new scene into the category. + categoryScenes.splice(position + 1, 0, { id: id, contributors: contributorList }); + + // Update the gallery strings, inserting the new item next to the selected item. + const newGalleryStrings = {}; + for (const key in galleryStrings) { + newGalleryStrings[key] = galleryStrings[key]; + if (key === positionCamelCase) { + newGalleryStrings[newSceneIdCamelCase] = newSceneStrings; + } + } + + galleryLocaleData.galleryData = newGalleryStrings; +} else { + // The scene is not for the Gallery webpage. The new scene is added at the end of the gallery strings. + galleryStrings[newSceneIdCamelCase] = newSceneStrings; +} + +// Output the gallery scene. +const scenePath = path.join(__dirname, `../data/galleryScenes/${id}.json`); +fs.writeFileSync(scenePath, JSON.stringify(sceneData, null, 2)); + +// Output the gallery list. +const galleryListPath = path.join(__dirname, '../data/galleryList.json'); +fs.writeFileSync(galleryListPath, JSON.stringify(galleryList, null, 2)); + +// Output the gallery locale data. +const galleryLocalePath = path.join(__dirname, '../locales/en/gallery.json'); +fs.writeFileSync(galleryLocalePath, JSON.stringify(galleryLocaleData, null, 2)); + +console.log('The scene has been successfully added to the gallery.'); +console.log('If some of the contributors are new, please add their names manually to the /data/contributors.json file.'); \ No newline at end of file diff --git a/scripts/addToModules.mjs b/scripts/addToModules.mjs new file mode 100644 index 00000000..612546a0 --- /dev/null +++ b/scripts/addToModules.mjs @@ -0,0 +1,234 @@ +import inquirer from 'inquirer'; +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import jsonUrl from 'json-url'; +import { type } from 'os'; +import { index } from 'mathjs'; + + +// Convert import.meta.url to a file path and determine the directory +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Load the module data. +const moduleList = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/moduleList.json')).toString()); + +// List all existing modules IDs, which are the file name of the json files in the /data/moduleScenes directory. +const sceneFiles = fs.readdirSync(path.join(__dirname, '../data/moduleScenes')); +const sceneIDs = sceneFiles.filter((file) => file.endsWith('.json')).map((file) => file.replace('.json', '')); + +// Load the English data of the modules. +const moduleLocaleData = JSON.parse(fs.readFileSync(path.join(__dirname, '../locales/en/modules.json'), 'utf8')); +const moduleStrings = moduleLocaleData.moduleData; + +// Create a dictionary mapping the IDs to the English titles. +const moduleIDToTitle = {}; +sceneIDs.forEach((id) => { + moduleIDToTitle[id] = moduleStrings[id].title; +}); + +// Prompt the requirement to the user. +console.log('Welcome to the module item creation tool.'); +console.log(''); +console.log('Plrease read the requirements for the new module item:'); +console.log('1. The ID of the module (and its dependencies if any) should be in PascalCase English. The ID of the main module (not including dependencies) should not be the same as one already in the module list.'); +console.log('2. All parameter names should contains only letters, numbers, and underscores, and should not start with a number, and should not cause conflicts when underscores are removed.'); +console.log('3. You should make a scene containing the module (and its dependencies if any), with a minimal example of the module usage to be used in the thumbnail.'); +console.log('4. The module and the example usage should not contain translatable text (put them in the description instead). If variable names contain words, they should be in English.'); +console.log('5. The scene must contain one square CropBox object. To create a CropBox object, click File -> Export PNG/SVG (but no need to actually export the image). To make it square, set the two coordinates of the crop box to the same value in the object bar. Do not adjust image format and resolution.') +console.log('6. If the scene involves infinite numbers of rays (e.g. repeated reflection in a cavity), you should click "More options..." and set a suitable "Ray count limit" for the CropBox to avoid infinite loops.') +console.log('7. When the scene is ready, click File -> Copy Sharable Link. The shared URL will be used to provide the scene data. Ignore the warning if the URL is too long.'); +console.log(''); + +// Prompt the user for the scene data (the shared URL). +const sceneURLInput = await inquirer.prompt({ + type: 'editor', + name: 'sceneURL', + message: "The shared URL of the scene:", +}); +console.log(''); + +// Decode the hash part of the URL (LZMA compressed JSON) using json-url. +const sceneData = await jsonUrl('lzma').decompress(sceneURLInput.sceneURL.split('#')[1]); + +const moduleIDsInScene = Object.keys(sceneData.modules); + +// Ensure that all module names are in PascalCase and contains only letters and numbers, and is not starting with a number, and the parameter names conatins only letters, numbers, and underscores, and is not starting with a number. +moduleIDsInScene.forEach((moduleID) => { + if (!/^[A-Z][a-zA-Z0-9]*$/.test(moduleID)) { + console.log(`Error: The module name "${moduleID}" is not in PascalCase or contains invalid characters.`); + process.exit(1); + } +}); + +// See if there are any modules in the scene. If there are more than one, prompt the user to choose one (unless the name of the scene matches one of the module IDs). +let moduleID; +if (moduleIDsInScene.length === 1) { + moduleID = moduleIDsInScene[0]; +} else if (moduleIDsInScene.length > 1) { + if (sceneData.name in moduleIDsInScene) { + moduleID = sceneData.name; + } else { + const moduleIDInput = await inquirer.prompt({ + type: 'list', + name: 'moduleID', + message: "Choose the main module of the scene:", + choices: moduleIDsInScene, + }); + console.log(''); + + moduleID = moduleIDInput.moduleID; + } +} else { + console.log('Error: No modules found in the scene.'); + process.exit(1); +} + +// Ensure that the module ID is not already in the module list. +if (sceneIDs.includes(moduleID)) { + console.log(`Error: The module ID "${moduleID}" is already in the module list.`); + process.exit(1); +} + +// Set the name of the scene to the module ID. +sceneData.name = moduleID; + +// Ensure that the scene data contains a square CropBox object. +let cropBoxThumbnail; +for (const obj of sceneData.objs) { + if (obj.type === 'CropBox') { + if (Math.abs((obj.p4.x - obj.p1.x) - (obj.p4.y - obj.p1.y)) < 1e-6) { + cropBoxThumbnail = obj; + } + } +} + +if (!cropBoxThumbnail) { + console.log('Error: No square CropBox object found in the scene.'); + process.exit(1); +} + +// Collect the keys for the new module. +const newKeys = ['title', 'description']; +for (let i = 1; i <= (sceneData.modules[moduleID].numPoints || 0); i++) { + newKeys.push(`point${i}`); +} +for (const param of sceneData.modules[moduleID].params) { + const paramName = param.split('=')[0]; + + // The key is the parameter name with underscores removed. + const key = paramName.replace(/_/g, ''); + + // Ensure that the key contains only letters and numbers, and is not starting with a number. + if (!/^[A-Za-z][A-Za-z0-9]*$/.test(key)) { + console.log(`Error: The parameter name "${paramName}" contains invalid characters.`); + process.exit(1); + } + + // Ensure that the key does not conflict with existing keys. + if (newKeys.includes(key)) { + console.log(`Error: The parameter name "${paramName}" conflicts with an existing key "${key}".`); + process.exit(1); + } +} + +// Prompt the user for the title, description, and specification of the module. +console.log('Please provide the title, description, and specificaiton of the module. They must be in English. If you want to provide translations, please do it after the module is added to the module list. The description and specification are in Markdown format, with each item in the specification having only a single line (do not include the bullet point). To include inline LaTeX equations, use the \\( and \\) delimiters. To include displayed LaTeX equation, use \\begin{equation} and \\end{equaion}. The equation will be rendered using MathJax. To include a link to a scene in the gallery, use the format [title](/gallery/SCENE_ID).'); + +const fields = [ + { + type: 'text', + name: 'title', + message: 'Title of the module:', + default: moduleID.replace(/([A-Z])/g, ' $1').trim() + }, + { + type: 'editor', + name: 'description', + message: 'Description of the module:' + } +]; + +for (let i = 1; i <= (sceneData.modules[moduleID].numPoints || 0); i++) { + fields.push({ + type: 'text', + name: `point${i}`, + message: `Description of the ${i}${i === 1 ? 'st' : i === 2 ? 'nd' : i === 3 ? 'rd' : 'th'} control point:` + }); +} + +for (const param of sceneData.modules[moduleID].params) { + const paramName = param.split('=')[0]; + fields.push({ + type: 'text', + name: paramName.replace(/_/g, ''), + message: `Description of the parameter "${paramName}":` + }); +} + +const moduleInput = await inquirer.prompt(fields); +console.log(''); + +const newStrings = {}; +for (const key of newKeys) { + newStrings[key] = moduleInput[key]; +} +newStrings.description = newStrings.description.trim(); + +// Ask the user for the position of the module in the module list. There is no category for now. One should not put the new module in the first position of the list. +const category = 'defaultCategory'; +console.log('Please provide the position of the module in the module list. The module will be placed after the selected module. If there are existing modules related to the new module, you can place the new module after them. Otherwise, it is recommended to place the new module at the end of the list.'); +const categoryModules = moduleList.find((category1) => category1.id === category).content; +const categoryModuleTitles = categoryModules.map((module1) => moduleIDToTitle[module1.id]); +const modulePositionInput = await inquirer.prompt({ + type: 'list', + name: 'position', + message: 'The position of the module in the module list:', + choices: categoryModuleTitles.map((title, index) => ({name: title, value: index})), + loop: false, +}); +console.log(''); + +const position = modulePositionInput.position; +const positionID = categoryModules[position].id; + +// Ask the name of the contributors. +console.log('Please provide the name of the contributor(s) of the module. The name will be displayed in the module list as well as the About page. The name can be a pseudonym or a real name, but must be in Latin characters. If the contributor has contributed before, please use the same name. If the author has a GitHub account, it is recommended to use the GitHub username or the "name" field in the GitHub profile if it is in Latin characters. If the module has multiple contributors, separate the names by semicolons, and should sort by the chronological order of the contributions. If a dependency is used, the name of the contributor(s) of the dependency should only be included if the dependency is not in the module list.'); +const contributorsPrompt = await inquirer.prompt({ + type: 'text', + name: 'contributors', + message: "The name of the contributor(s):", +}); +console.log(''); + +const contributors = contributorsPrompt.contributors; +const contributorList = contributors.split(';').map((name) => name.trim()); + +// Insert the new module into the category. +categoryModules.splice(position + 1, 0, {id: moduleID, contributors: contributorList}); + +// Update the module strings, inserting the new keys next to the selected module. +const newModuleStrings = {}; +for (const key in moduleStrings) { + newModuleStrings[key] = moduleStrings[key]; + if (key === positionID) { + newModuleStrings[moduleID] = newStrings; + } +} +moduleLocaleData.moduleData = newModuleStrings; + +// Output the module scene. +const moduleScenePath = path.join(__dirname, `../data/moduleScenes/${moduleID}.json`); +fs.writeFileSync(moduleScenePath, JSON.stringify(sceneData, null, 2)); + +// Output the module list. +const moduleListPath = path.join(__dirname, '../data/moduleList.json'); +fs.writeFileSync(moduleListPath, JSON.stringify(moduleList, null, 2)); + +// Output the module locale data. +const moduleLocalePath = path.join(__dirname, '../locales/en/modules.json'); +fs.writeFileSync(moduleLocalePath, JSON.stringify(moduleLocaleData, null, 2)); + +console.log('The module item has been successfully added.'); +console.log('If some of the contributors are new, please add their names manually to the /data/contributors.json file.'); \ No newline at end of file diff --git a/scripts/buildImages.js b/scripts/buildImages.mjs similarity index 56% rename from scripts/buildImages.js rename to scripts/buildImages.mjs index 0a2871c6..01525492 100644 --- a/scripts/buildImages.js +++ b/scripts/buildImages.mjs @@ -1,19 +1,39 @@ -const fs = require('fs'); -const path = require('path'); -const { Scene, Simulator, sceneObjs, geometry } = require(path.join(__dirname, '../dist-node/main.js')); - -const { createCanvas, loadImage } = require('canvas'); -const sharp = require('sharp'); -const { info } = require('console'); - -const langs = ['en', 'pl', 'zh-CN', 'zh-TW']; -const dirs = { - 'en': path.join(__dirname, '../dist/gallery/'), - 'pl': path.join(__dirname, '../dist/pl/gallery/'), - 'zh-CN': path.join(__dirname, '../dist/cn/gallery/'), - 'zh-TW': path.join(__dirname, '../dist/tw/gallery/') +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import rayOptics from '../dist-node/main.js'; +import { createCanvas, loadImage } from 'canvas'; +import sharp from 'sharp'; + +// Convert import.meta.url to a file path and determine the directory +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// List all existing languages, which are the directories in the /locales directory. Put English first. +const langs = ['en'].concat(fs.readdirSync(path.join(__dirname, '../locales')).filter((file) => !file.includes('.') && file !== 'en')); + +// Load the locale routes data +const routesData = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/localeRoutes.json'), 'utf8')); + +// Fill the rest of the locale rountes +for (const lang of langs) { + if (routesData[lang] === undefined) { + routesData[lang] = '/' + lang; + } +} + +// Get all the languages where the corresponding gallery directory exists +const galleryLangs = []; +const galleryDirs = {}; +for (const lang of langs) { + if (fs.existsSync(path.join(__dirname, '../dist' + routesData[lang] + '/gallery/'))) { + galleryLangs.push(lang); + galleryDirs[lang] = path.join(__dirname, '../dist' + routesData[lang] + '/gallery/'); + } } +const modulesDir = path.join(__dirname, '../dist/modules/'); + const canvasLight = createCanvas(); const canvasBelowLight = createCanvas(); const canvasAboveLight = createCanvas(); @@ -28,12 +48,12 @@ const ctxGrid = canvasGrid.getContext('2d'); const ctxVirtual = canvasVirtual.getContext('2d'); const ctxFinal = canvasFinal.getContext('2d'); -const scene = new Scene(); -const simulator = new Simulator(scene, ctxLight, ctxBelowLight, ctxAboveLight, ctxGrid, ctxVirtual, false); +const scene = new rayOptics.Scene(); +const simulator = new rayOptics.Simulator(scene, ctxLight, ctxBelowLight, ctxAboveLight, ctxGrid, ctxVirtual, false); function loadScene(sceneJson, callback, backgroundImage) { if (sceneJson.backgroundImage) { - loadImage(dirs.en + sceneJson.backgroundImage).then((image) => { + loadImage(galleryDirs.en + sceneJson.backgroundImage).then((image) => { sceneJson.backgroundImage = null; loadScene(sceneJson, callback, image); }); @@ -124,8 +144,8 @@ function exportImageFromCropBox(cropBox, filename, skipLight, callback) { }); } -function exportImages(itemId, lang, isThumbnail, callback) { - const sceneJson = JSON.parse(fs.readFileSync(dirs[lang] + itemId + '.json', 'utf8')); +function exportImages(dir, itemId, lang, isThumbnail, callback) { + const sceneJson = JSON.parse(fs.readFileSync(dir + itemId + '.json', 'utf8')); loadScene(sceneJson, function () { // Find crop boxes, where the preview one is rectangular and the thumbnail one is square let cropBoxPreview = null; @@ -140,49 +160,66 @@ function exportImages(itemId, lang, isThumbnail, callback) { } } - if (!cropBoxPreview) { - throw new Error('No preview crop box found'); + if (cropBoxPreview) { + cropBoxPreview.width = 2280; + } else if (!isThumbnail) { + console.error('No preview crop box found for ' + itemId + ' in ' + lang); + process.exit(1); } - if (!cropBoxThumbnail) { - throw new Error('No thumbnail crop box found'); + if (cropBoxThumbnail) { + cropBoxThumbnail.width = 500; + } else if (isThumbnail) { + console.error('No thumbnail crop box found for ' + itemId + ' in ' + lang); + process.exit(1); } - cropBoxPreview.width = 2280; - cropBoxThumbnail.width = 500; - const skipLight = lang !== 'en'; // Different languages only differs in text, so we only need to re-render the light layer for the first language in the list. // Export preview image - exportImageFromCropBox(isThumbnail ? cropBoxThumbnail : cropBoxPreview, dirs[lang] + itemId + (isThumbnail ? '-thumbnail' : ''), skipLight, function () { + exportImageFromCropBox(isThumbnail ? cropBoxThumbnail : cropBoxPreview, dir + itemId + (isThumbnail ? '-thumbnail' : ''), skipLight, function () { callback(); }); }); } -function exportImagesPromise(itemId, lang, isThumbnail) { +function exportImagesPromise(dir, itemId, lang, isThumbnail) { return new Promise((resolve) => { - exportImages(itemId, lang, isThumbnail, resolve); + exportImages(dir, itemId, lang, isThumbnail, resolve); }); } -// Get all JSON files in the input directory -const items = fs.readdirSync(dirs.en).filter(file => file.endsWith('.json') && file !== 'data.json').map(file => file.slice(0, -5)); +// Get all JSON files in the gallery directory +const galleryItems = fs.readdirSync(galleryDirs.en).filter(file => file.endsWith('.json') && file !== 'data.json').map(file => file.slice(0, -5)).filter(file => !file.startsWith('module-example-')); -async function exportAllImages() { +async function exportAllGalleryImages() { const beginTime = Date.now(); - for (let item of items) { - for (isThumbnail of [false, true]) { - for (let lang of langs) { - if (fs.existsSync(dirs[lang] + item + '.json')) { + for (let item of galleryItems) { + for (let isThumbnail of [false, true]) { + for (let lang of galleryLangs) { + if (fs.existsSync(galleryDirs[lang] + item + '.json')) { const time = Date.now(); - await exportImagesPromise(item, lang, isThumbnail); + await exportImagesPromise(galleryDirs[lang], item, lang, isThumbnail); console.log('Exported ' + (isThumbnail ? 'thumbnail' : 'preview') + ' for ' + item + ' in ' + lang + ' in ' + (Date.now() - time) + 'ms'); } } } } - console.log('Exported all images in ' + (Date.now() - beginTime) + 'ms'); + console.log('Exported all gallery images in ' + (Date.now() - beginTime) + 'ms'); } -exportAllImages(); \ No newline at end of file +// Get all JSON files in the modules directory, note that it is not multilingual +const moduleItems = fs.readdirSync(modulesDir).filter(file => file.endsWith('.json') && file !== 'data.json').map(file => file.slice(0, -5)); + +async function exportAllModuleImages() { + const beginTime = Date.now(); + for (let item of moduleItems) { + await exportImagesPromise(modulesDir, item, 'en', true); + } + console.log('Exported all module images in ' + (Date.now() - beginTime) + 'ms'); +} + +await exportAllGalleryImages(); +await exportAllModuleImages(); + + diff --git a/scripts/buildInlineLocaleData.mjs b/scripts/buildInlineLocaleData.mjs new file mode 100644 index 00000000..73d893c3 --- /dev/null +++ b/scripts/buildInlineLocaleData.mjs @@ -0,0 +1,90 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +// Convert import.meta.url to a file path and determine the directory +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Given a json object, calculate the total number of strings in the object, but string keys of the form key_suffix are treated as the same string as key. +function countStrings(json) { + const stringKeys = new Set(); + let count = 0; + for (const key in json) { + if (typeof json[key] === 'string') { + if (key.includes('_')) { + stringKeys.add(key.split('_')[0]); + } else { + stringKeys.add(key); + } + } else if (typeof json[key] === 'object') { + count += countStrings(json[key]); + } + } + return count + stringKeys.size; +} + +export default function() { + const localeData = {}; + + // List all existing languages, which are the directories in the /locales directory. Put English first. + const langs = ['en'].concat(fs.readdirSync(path.join(__dirname, '../locales')).filter((file) => !file.includes('.') && file !== 'en')); + + // Load the locale routes data + const routesData = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/localeRoutes.json'), 'utf8')); + + for (const lang of langs) { + // See if main.json and simulator.json both exist in the language directory. Otherwise, skip this language. + const mainPath = path.join(__dirname, '../locales', lang, 'main.json'); + const simulatorPath = path.join(__dirname, '../locales', lang, 'simulator.json'); + if (!fs.existsSync(mainPath) || !fs.existsSync(simulatorPath)) { + continue; + } + + localeData[lang] = {}; + + // Load the JSON data for the language. + const mainData = JSON.parse(fs.readFileSync(mainPath, 'utf8')); + const simulatorData = JSON.parse(fs.readFileSync(simulatorPath, 'utf8')); + + // Set the name of the language + localeData[lang].name = mainData.meta.languageName || lang; + + // Set the total number of strings in the language + localeData[lang].numStrings = countStrings(mainData) + countStrings(simulatorData); + + // Set the routes for the language + if (routesData[lang] !== undefined) { + localeData[lang].route = routesData[lang]; + } + + // Set whether the gallery page is available. + const galleryPath = path.join(__dirname, '../locales', lang, 'gallery.json'); + if (fs.existsSync(galleryPath) && JSON.parse(fs.readFileSync(galleryPath, 'utf8')).galleryPage) { + localeData[lang].gallery = true; + } + + // Set whether the modules list is available. + const modulePath = path.join(__dirname, '../locales', lang, 'modules.json'); + if (fs.existsSync(modulePath) && JSON.parse(fs.readFileSync(modulePath, 'utf8')).modulesPage) { + localeData[lang].modules = true; + } + + // Set whether the module tutorial is available. + if (fs.existsSync(modulePath) && JSON.parse(fs.readFileSync(modulePath, 'utf8')).moduleTutorial) { + localeData[lang].moduleTutorial = true; + } + + // Set whether the about page is available + if (mainData.aboutPage) { + localeData[lang].about = true; + } + + // Set the welcome message + if (simulatorData.welcome) { + localeData[lang].welcome = simulatorData.welcome; + } + } + + return localeData; +} diff --git a/scripts/buildScenes.mjs b/scripts/buildScenes.mjs new file mode 100644 index 00000000..8e0a621e --- /dev/null +++ b/scripts/buildScenes.mjs @@ -0,0 +1,164 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + + +// Convert import.meta.url to a file path and determine the directory +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// List all existing scenes IDs, which are the file name of the json files in the /data/galleryScenes directory. +const sceneFiles = fs.readdirSync(path.join(__dirname, '../data/galleryScenes')); +const sceneIDs = sceneFiles.filter((file) => file.endsWith('.json')).map((file) => file.replace('.json', '')); + +// Create a dictionary converting the scene IDs to the camelCase format. +const sceneIDToCamelCase = {}; +sceneIDs.forEach((id) => { + sceneIDToCamelCase[id] = id.toLowerCase().replace(/-([a-z])/g, (g) => g[1].toUpperCase()); +}); + +// List all existing languages, which are the directories in the /locales directory. +const langs = fs.readdirSync(path.join(__dirname, '../locales')).filter((file) => !file.includes('.')); + +// Load the locale routes. +const localeRoutes = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/localeRoutes.json')).toString()); + +// Create the stringsKeys dictionary to store the extracted strings in the format stringsKeys[lang][string_id] = string. +const stringKeys = {}; +langs.forEach((lang) => { + stringKeys[lang] = {}; + + // Load the strings from /locales/{lang}/gallery.json if it exists. + const galleryStringsPath = path.join(__dirname, `../locales/${lang}/gallery.json`); + if (fs.existsSync(galleryStringsPath)) { + const galleryStrings = JSON.parse(fs.readFileSync(galleryStringsPath).toString()).galleryData; + // Extract the strings from the galleryStrings object. + sceneIDs.forEach((id) => { + if (galleryStrings[sceneIDToCamelCase[id]]) { + const scene = galleryStrings[sceneIDToCamelCase[id]]; + for (const key in scene) { + if (key === 'title') { + stringKeys[lang][`${id}.title`] = scene[key]; + } else if (key === 'description') { + stringKeys[lang][`${id}.description`] = scene[key]; + } else { + if (!stringKeys[lang][key]) { + stringKeys[lang][key] = scene[key]; + } else { + console.log(`Duplicate string key found: ${key} in lang ${lang}, scene ${id}.`); + } + } + } + } + }); + + // Extract the common strings. + if (galleryStrings.common) { + for (const key in galleryStrings.common) { + if (!stringKeys[lang][key]) { + stringKeys[lang][key] = galleryStrings.common[key]; + } else { + console.log(`Duplicate string key found: ${key} in lang ${lang}, common strings.`); + } + } + } + } +}); + +sceneIDs.forEach((id) => { + // Load the scene data from /data/galleryScenes/{id}.json. + const sceneData = JSON.parse(fs.readFileSync(path.join(__dirname, `../data/galleryScenes/${id}.json`)).toString()); + + // Find the CropBox objects. + let cropBoxPreview = null; + let cropBoxThumbnail = null; + for (const obj of sceneData.objs) { + if (obj.type === 'CropBox') { + if (Math.abs((obj.p4.x - obj.p1.x) - (obj.p4.y - obj.p1.y)) < 1e-6) { + cropBoxThumbnail = obj; + } else { + cropBoxPreview = obj; + } + } + } + + if (cropBoxPreview) { + // Adjust the width, height, origin, and scale of the scene based on he rectangular crop box + let effectiveWidth = cropBoxPreview.p4.x - cropBoxPreview.p1.x; + let effectiveHeight = cropBoxPreview.p4.y - cropBoxPreview.p1.y; + let effectiveOriginX = cropBoxPreview.p1.x; + let effectiveOriginY = cropBoxPreview.p1.y; + + let padding = effectiveWidth * 0.25; + effectiveWidth += padding * 2; + effectiveHeight += padding * 2; + effectiveOriginX -= padding; + effectiveOriginY -= padding; + + sceneData.width = effectiveWidth; + sceneData.height = effectiveHeight; + sceneData.origin = {x: -effectiveOriginX, y: -effectiveOriginY}; + sceneData.scale = 1; + } + + langs.forEach((lang) => { + // The scene should be built in the language iff the title is translated. + if (stringKeys[lang][`${id}.title`]) { + // The title (name) of the scene should be put first. + const outputData = { + name: stringKeys[lang][`${id}.title`], + }; + + // Copy the rest of the scene data. + for (const key in sceneData) { + outputData[key] = JSON.parse(JSON.stringify(sceneData[key])); + } + + // Search for all TextLabel objects recursively and replace the text with the translated strings. + const replaceText = (obj) => { + if (obj.type === 'TextLabel') { + if (obj.text && obj.text.startsWith('{{') && obj.text.endsWith('}}')) { + const stringID = obj.text.substring(2, obj.text.length - 2); + if (stringKeys[lang][stringID]) { + obj.text = stringKeys[lang][stringID]; + } else if (stringKeys.en[stringID]) { + obj.text = stringKeys.en[stringID]; + } else { + console.log(`String not found: ${stringID} in ${id}.json`); + } + } + } else { + for (const key in obj) { + if (typeof obj[key] === 'object') { + replaceText(obj[key]); + } + } + } + }; + replaceText(outputData); + + // Save the outputData to /dist/{locale}/gallery/{id}.json. + const outputFolder = path.join(__dirname, `../dist${localeRoutes[lang] !== undefined ? localeRoutes[lang] : ('/' + lang)}/gallery`); + if (!fs.existsSync(outputFolder)) { + fs.mkdirSync(outputFolder, { recursive: true }); + } + fs.writeFileSync(path.join(outputFolder, `${id}.json`), JSON.stringify(outputData, null, 2)); + } + }); +}); + +// Copy all PNG files (background images) in /data/galleryScenes to /dist/gallery. +const imageFiles = sceneFiles.filter((file) => file.endsWith('.png')); +imageFiles.forEach((file) => { + fs.copyFileSync(path.join(__dirname, `../data/galleryScenes/${file}`), path.join(__dirname, `../dist/gallery/${file}`)); +}); + +console.log('All Gallery scenes built successfully.'); + +// Build the scenes for the modules. Currently just copy the files from /data/moduleScenes to /dist/modules. +const moduleFiles = fs.readdirSync(path.join(__dirname, '../data/moduleScenes')); +moduleFiles.forEach((file) => { + fs.copyFileSync(path.join(__dirname, `../data/moduleScenes/${file}`), path.join(__dirname, `../dist/modules/${file}`)); +}); + +console.log('All Module scenes built successfully.'); diff --git a/scripts/buildTranslations.js b/scripts/buildTranslations.js deleted file mode 100644 index b3a6d949..00000000 --- a/scripts/buildTranslations.js +++ /dev/null @@ -1,38 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -function calculateCompleteness(localeDir) { - const completeness = {}; - const files = fs.readdirSync(localeDir); - - files.forEach(file => { - if (path.extname(file) === '.json' && file !== 'template.json' && file !== 'completeness.json') { - const language = path.basename(file, '.json'); - const content = JSON.parse(fs.readFileSync(path.join(localeDir, file), 'utf8')); - - let total = 0; - let incomplete = 0; - - Object.values(content).forEach(item => { - total++; - if (item.incomplete) { - incomplete++; - } - }); - - const completePercentage = Math.round((total - incomplete) / total * 100); - completeness[language] = completePercentage; - } - }); - - return completeness; -} - -const localeDir = path.join(__dirname, '../locales'); - -const completeness = calculateCompleteness(localeDir); -fs.writeFileSync( - path.join(localeDir, 'completeness.json'), - JSON.stringify(completeness, null, 2) -); -console.log('Translation completeness calculated and saved.'); \ No newline at end of file diff --git a/scripts/buildWebpages.js b/scripts/buildWebpages.js deleted file mode 100644 index 514cbda7..00000000 --- a/scripts/buildWebpages.js +++ /dev/null @@ -1,22 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const { execSync } = require('child_process'); - -// Copy the third-party libraries used by the non-app webpages (not migrated to Webpack yet) to the /dist/thirdparty folder -fs.mkdirSync(path.join(__dirname, '../dist/thirdparty'), { recursive: true }); -fs.copyFileSync(path.join(__dirname, '../node_modules/jquery/dist/jquery.min.js'), path.join(__dirname, '../dist/thirdparty/jquery.min.js')); -fs.mkdirSync(path.join(__dirname, '../dist/thirdparty/bootstrap'), { recursive: true }); -fs.copyFileSync(path.join(__dirname, '../node_modules/bootstrap3/dist/css/bootstrap.min.css'), path.join(__dirname, '../dist/thirdparty/bootstrap/bootstrap.min.css')); -fs.copyFileSync(path.join(__dirname, '../node_modules/bootstrap3/dist/js/bootstrap.min.js'), path.join(__dirname, '../dist/thirdparty/bootstrap/bootstrap.min.js')); -fs.mkdirSync(path.join(__dirname, '../dist/thirdparty/fonts'), { recursive: true }); -fs.copyFileSync(path.join(__dirname, '../node_modules/bootstrap3/dist/fonts/glyphicons-halflings-regular.woff2'), path.join(__dirname, '../dist/thirdparty/fonts/glyphicons-halflings-regular.woff2')); - -// Copy the non-app webpages and data (not migrated to Webpack yet) to the /dist folder -fs.mkdirSync(path.join(__dirname, '../dist'), { recursive: true }); -fs.cpSync(path.join(__dirname, '../src/webpages'), path.join(__dirname, '../dist'), { recursive: true }); - -// Run the old node.js scripts in the non-app webpages folders -const outputGallery = execSync('node ' + path.join(__dirname, '../dist/gallery/generate-gallery.js'), { cwd: path.join(__dirname, '../dist/gallery') }); -console.log(outputGallery.toString()); -const outputModules = execSync('node ' + path.join(__dirname, '../dist/modules/generate-modules.js'), { cwd: path.join(__dirname, '../dist/modules') }); -console.log(outputModules.toString()); diff --git a/scripts/buildWebpages.mjs b/scripts/buildWebpages.mjs new file mode 100644 index 00000000..186b3c06 --- /dev/null +++ b/scripts/buildWebpages.mjs @@ -0,0 +1,605 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import Handlebars from 'handlebars'; +import { marked } from 'marked'; +import i18next from 'i18next'; +import simpleGit from 'simple-git'; + + +// Convert import.meta.url to a file path and determine the directory +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Copy the third-party libraries used by the non-app webpages to the /dist/thirdparty folder +fs.mkdirSync(path.join(__dirname, '../dist/thirdparty'), { recursive: true }); +fs.copyFileSync(path.join(__dirname, '../node_modules/jquery/dist/jquery.min.js'), path.join(__dirname, '../dist/thirdparty/jquery.min.js')); +fs.mkdirSync(path.join(__dirname, '../dist/thirdparty/bootstrap'), { recursive: true }); +fs.copyFileSync(path.join(__dirname, '../node_modules/bootstrap3/dist/css/bootstrap.min.css'), path.join(__dirname, '../dist/thirdparty/bootstrap/bootstrap.min.css')); +fs.copyFileSync(path.join(__dirname, '../node_modules/bootstrap3/dist/js/bootstrap.min.js'), path.join(__dirname, '../dist/thirdparty/bootstrap/bootstrap.min.js')); +fs.mkdirSync(path.join(__dirname, '../dist/thirdparty/fonts'), { recursive: true }); +fs.copyFileSync(path.join(__dirname, '../node_modules/bootstrap3/dist/fonts/glyphicons-halflings-regular.woff2'), path.join(__dirname, '../dist/thirdparty/fonts/glyphicons-halflings-regular.woff2')); + +// List all existing languages, which are the directories in the /locales directory. Put English first. +const langs = ['en'].concat(fs.readdirSync(path.join(__dirname, '../locales')).filter((file) => !file.includes('.') && file !== 'en')); + +// Load the locale routes data +const routesData = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/localeRoutes.json'), 'utf8')); + +// Fill the rest of the locale rountes +for (const lang of langs) { + if (routesData[lang] === undefined) { + routesData[lang] = '/' + lang; + } +} + + +// Load and process contributors data +const git = simpleGit(); +const contributors = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/contributors.json'), 'utf8')); + +// Initialize commit counts +contributors.forEach(c => c.commits = 0); + +// Get Git contributors +const logEntries = await git.raw([ + 'log', + '--reverse', + '--pretty=format:%H|%an|%ae|%aI|%s|%P' +]); + +const firstEntryHash = logEntries.split('\n')[0].split('|')[0]; + +if (firstEntryHash !== 'c3b4eea281d34fc2aee5186510cceb50cd9db2f5') { + console.log('The repo is not completely cloned. Cannot generate contributors list.'); + process.exit(1); +} + +// Process git log entries +logEntries.split('\n').forEach(entry => { + const [hash, name, email, date, message, parents] = entry.split('|'); + + if (!name || !email || !date) { + console.warn('Skipping invalid log entry:', entry); + return; + } + + // Rule out merge commits + const parentCount = parents.split(' ').filter(Boolean).length; + if (parentCount > 1) { + return; + } + + const contributor = contributors.find(c => (c.githubEmails || []).includes(email)); + if (contributor) { + contributor.commits += 1; + } +}); + +// Sort contributors by commit count +const sortedContributors = contributors + .filter(c => !c.isMainAuthor) + .sort((a, b) => b.commits - a.commits); +const sortedMainAuthors = contributors + .filter(c => c.isMainAuthor) + .sort((a, b) => b.commits - a.commits); + + +// Load the gallery list +const galleryList = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/galleryList.json'), 'utf8')); + +// List all existing galleryscenes IDs, which are the file name of the json files in the /data/galleryScenes directory. +const galleryFiles = fs.readdirSync(path.join(__dirname, '../data/galleryScenes')); +const galleryIDs = galleryFiles.filter((file) => file.endsWith('.json')).map((file) => file.replace('.json', '')); + +// List all IDs which are in the galleryList +const galleryIDInList = {}; +for (const category of galleryList) { + for (const item of category.content) { + galleryIDInList[item.id] = true; + } +} + +// Create a dictionary converting the scene IDs to the contributors. +const galleryIDContributors = {}; +for (const category of galleryList) { + for (const item of category.content) { + galleryIDContributors[item.id] = item.contributors; + } +} + +// Create a dictionary converting the scene IDs to the camelCase format. +const galleryIDToCamelCase = {}; +galleryIDs.forEach((id) => { + galleryIDToCamelCase[id] = id.toLowerCase().replace(/-([a-z])/g, (g) => g[1].toUpperCase()); +}); + +const galleryCategories = galleryList.map(item => item.id); + +const galleryCategoryToCamelCase = {}; +galleryCategories.forEach((category) => { + galleryCategoryToCamelCase[category] = category.toLowerCase().replace(/-([a-z])/g, (g) => g[1].toUpperCase()); +}); + +// Load the module list +const moduleList = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/moduleList.json'), 'utf8')); + +// Load the English module data +const moduleData = JSON.parse(fs.readFileSync(path.join(__dirname, '../locales/en/modules.json'), 'utf8')).moduleData; + +// Create a dictionary mapping the module IDs to the array of control point sequence keys and parameters keys +const moduleControlPointSequenceKeys = {}; +const moduleParametersKeys = {}; +for (const id in moduleData) { + moduleControlPointSequenceKeys[id] = Object.keys(moduleData[id]).filter(key => key.startsWith('point')); + moduleParametersKeys[id] = Object.keys(moduleData[id]).filter(key => !key.startsWith('point') && key != 'title' && key != 'description'); +} + +// List all module ids in the moduleList +const moduleIDs = []; +for (const category of moduleList) { + for (const item of category.content) { + moduleIDs.push(item.id); + } +} + +const homeLangs = []; +const aboutLangs = []; +const galleryLangs = []; +const galleryItemsLangs = {}; +const modulesLangs = []; +const moduleItemsLangs = {}; +const moduleTutorialLangs = []; + +for (const id of galleryIDs) { + galleryItemsLangs[id] = []; +} + +for (const id of moduleIDs) { + moduleItemsLangs[id] = []; +} + +const rootAbsUrl = "https://phydemo.app/ray-optics"; +const urlMaps = {}; +const langNames = {}; +const i18nextResources = {}; + +// Load the available languages for each webpage and create the URL maps +for (const lang of langs) { + // See if main.json and simulator.json both exist in the language directory. Otherwise, skip this language. + const mainPath = path.join(__dirname, '../locales', lang, 'main.json'); + const simulatorPath = path.join(__dirname, '../locales', lang, 'simulator.json'); + const galleryPath = path.join(__dirname, '../locales', lang, 'gallery.json'); + const modulesPath = path.join(__dirname, '../locales', lang, 'modules.json'); + if (!fs.existsSync(mainPath) || !fs.existsSync(simulatorPath)) { + continue; + } + + const mainData = JSON.parse(fs.readFileSync(mainPath, 'utf8')); + const simulatorData = JSON.parse(fs.readFileSync(simulatorPath, 'utf8')); + const galleryData = fs.existsSync(galleryPath) ? JSON.parse(fs.readFileSync(galleryPath, 'utf8')) : {}; + const modulesData = fs.existsSync(modulesPath) ? JSON.parse(fs.readFileSync(modulesPath, 'utf8')) : {}; + + // Add to the i18next resources + i18nextResources[lang] = { + main: mainData, + simulator: simulatorData, + gallery: galleryData, + modules: modulesData, + }; + + // Add the language name + langNames[lang] = mainData.meta.languageName || lang; + + urlMaps[lang] = { + "/simulator": "/simulator/" + (lang === 'en' ? '' : '?' + lang), + "/phydemo": "https://phydemo.app/", + "/email": "mailto:ray-optics@phydemo.app", + "/github": "https://github.com/ricktu288/ray-optics", + "/github/issues": "https://github.com/ricktu288/ray-optics/issues", + "/github/discussions": "https://github.com/ricktu288/ray-optics/discussions", + "/contributing": "https://github.com/ricktu288/ray-optics/blob/master/CONTRIBUTING.md", + "/contributing/gallery": "https://github.com/ricktu288/ray-optics/blob/master/CONTRIBUTING.md#contributing-items-to-the-gallery", + "/contributing/modules": "https://github.com/ricktu288/ray-optics/blob/master/CONTRIBUTING.md#contributing-modules", + "/license": "https://github.com/ricktu288/ray-optics/blob/master/LICENSE", + "/mathjs/syntax": "https://mathjs.org/docs/reference/functions/evaluate.html", + }; + + homeLangs.push(lang); + urlMaps[lang]['/home'] = routesData[lang] + '/'; + + if (mainData.aboutPage) { + aboutLangs.push(lang); + urlMaps[lang]['/about'] = routesData[lang] + '/about'; + } else { + urlMaps[lang]['/about'] = '/about'; + } + + if (galleryData.galleryPage) { + galleryLangs.push(lang); + urlMaps[lang]['/gallery'] = routesData[lang] + '/gallery/'; + } else { + urlMaps[lang]['/gallery'] = '/gallery/'; + } + + for (const id of galleryIDs) { + if (galleryData.galleryData && galleryData.galleryData[galleryIDToCamelCase[id]]) { + galleryItemsLangs[id].push(lang); + urlMaps[lang][`/gallery/${id}`] = routesData[lang] + '/gallery/' + id; + } else { + urlMaps[lang][`/gallery/${id}`] = '/gallery/' + id; + } + } + + if (modulesData.modulesPage) { + modulesLangs.push(lang); + urlMaps[lang]['/modules/modules'] = routesData[lang] + '/modules/modules.html'; + } else { + urlMaps[lang]['/modules/modules'] = '/modules/modules.html'; + } + + for (const id of moduleIDs) { + if (modulesData.moduleData && modulesData.moduleData[galleryIDToCamelCase[id]]) { + moduleItemsLangs[id].push(lang); + } + } + + if (modulesData.moduleTutorial) { + moduleTutorialLangs.push(lang); + urlMaps[lang]['/modules/tutorial'] = routesData[lang] + '/modules/tutorial'; + } else { + urlMaps[lang]['/modules/tutorial'] = '/modules/tutorial'; + } +} + +// Calculate the fraction of the gallery items that are translated for each language +const galleryItemsTranslated = {}; +for (const lang of galleryLangs) { + galleryItemsTranslated[lang] = galleryIDs.filter(id => galleryItemsLangs[id].includes(lang)).length / galleryIDs.length; +} + +// Initialize the i18next resources +i18next.init({ + lng: 'en', + fallbackLng: 'en', + load: 'currentOnly', + ns: ['main', 'simulator', 'gallery', 'modules'], + resources: i18nextResources, + interpolation: { + escapeValue: false + } +}); + +// Configure the marked renderer +marked.setOptions({ + breaks: true, +}); + +// Create the pages +for (const lang of homeLangs) { + // Change the language of i18next + i18next.changeLanguage(lang); + + // Format the list of items in the current language + function formatList(items) { + if (items.length === 0) return ''; + if (items.length === 1) return items[0]; + return i18next.t('main:meta.list', { + first: items[0], + others: formatList(items.slice(1)) + }); + } + + // Create the directory for the language in the /dist directory + const langDir = path.join(__dirname, '../dist', routesData[lang]); + fs.mkdirSync(langDir, { recursive: true }); + + // Register the Handlebars helper + Handlebars.registerHelper('t', function(key, options) { + let markdownText = i18next.t(key, options.hash); + + // Map the URLs in the markdown text + markdownText = markdownText.replace(/\[([^\]]+)\]\(([^\)]+)\)/g, (match, p1, p2) => { + if (urlMaps[lang][p2]) { + return `[${p1}](${urlMaps[lang][p2]})`; + } else { + return match; + } + }); + + // Wrap the inline LaTeX \(...\) in a code block + markdownText = markdownText.replace(/\\\((.*?)\\\)/g, (match, p1) => '`\\(' + p1 + '\\)`'); + + // Wrap the LaTeX equations in a code block + markdownText = markdownText.replace(/\\begin{equation}(.*?)\\end{equation}/g, (match, p1) => '```\\begin{equation}' + p1 + '\\end{equation}```'); + + // Convert the markdown text to HTML + let html = marked(markdownText).trim(); + + // Replace the inline LaTeX back to \(...\) + html = html.replace(/\\\((.*?)\\\)<\/code>/g, (match, p1) => '\\(' + p1 + '\\)'); + + // Replace the LaTeX equations back to \\begin{equation}...\end{equation} + html = html.replace(/\\begin{equation}(.*?)\\end{equation}<\/code>/g, (match, p1) => '\\begin{equation}' + p1 + '\\end{equation}'); + + // Remove the outer

tag + if (html.startsWith('

') && html.endsWith('

')) { + html = html.substring(3, html.length - 4); + } + + // If options contains "blank", replace the link with a target="_blank" link + if (options.hash.blank) { + html = html.replace(/${lang}`).join(' & ') + })); + } + return formatList(contribItems); + } + const aboutTemplate = Handlebars.compile(fs.readFileSync(path.join(__dirname, '../src/webpages/about.hbs'), 'utf8')); + const aboutData = { + title: i18next.t('main:pages.about') + ' - ' + i18next.t('main:project.name'), + ogImage: rootAbsUrl + '/img/image.png', + absUrl: rootAbsUrl + urlMaps[lang]['/about'], + lang: lang, + langName: langNames[lang], + supportedLangs: aboutLangs.map((lang) => { + return { + lang: lang, + name: langNames[lang], + url: rootUrl + urlMaps[lang]['/about'], + absUrl: rootAbsUrl + urlMaps[lang]['/about'], + }; + }), + imgUrl: rootUrl + '/img', + thirdpartyUrl: rootUrl + '/thirdparty', + homeUrl: rootUrl + urlMaps[lang]['/home'], + aboutUrl: rootUrl + urlMaps[lang]['/about'], + galleryUrl: rootUrl + urlMaps[lang]['/gallery'], + simulatorUrl: rootUrl + urlMaps[lang]['/simulator'], + isHome: false, + isGallery: false, + isAbout: true, + mainAuthors: sortedMainAuthors.map(c => { + const name = (c.name === 'Yi-Ting Tu' && lang.startsWith('zh') ? '凃懿庭 Yi-Ting Tu' : c.name); + const url = (c.name === 'Yi-Ting Tu') ? 'https://yitingtu.com' : ''; + return new Handlebars.SafeString(i18next.t('main:meta.parentheses', { + main: url ? `${name}` : name, + sub: formatContributions(c.contributions) + })); + }), + contributors: sortedContributors.map(c => { + return new Handlebars.SafeString(i18next.t('main:meta.parentheses', { + main: c.name, + sub: formatContributions(c.contributions) + })) + }), + } + fs.writeFileSync(path.join(langDir, 'about.html'), aboutTemplate(aboutData)); + } + + // Create the gallery webpage + if (galleryLangs.includes(lang)) { + // Create the gallery/ directory + const galleryDir = path.join(langDir, 'gallery'); + fs.mkdirSync(galleryDir, { recursive: true }); + const rootUrl = lang == 'en' ? '..' : '../..'; + + const galleryTemplate = Handlebars.compile(fs.readFileSync(path.join(__dirname, '../src/webpages/gallery.hbs'), 'utf8')); + const galleryData = { + title: i18next.t('main:pages.gallery') + ' - ' + i18next.t('main:project.name'), + ogImage: rootAbsUrl + '/img/image.png', + absUrl: rootAbsUrl + urlMaps[lang]['/gallery'], + lang: lang, + langName: langNames[lang], + supportedLangs: galleryLangs.map((lang) => { + return { + lang: lang, + name: langNames[lang], + url: rootUrl + urlMaps[lang]['/gallery'], + absUrl: rootAbsUrl + urlMaps[lang]['/gallery'], + translatedFraction: i18next.t('main:meta.parentheses', { + main: '', + sub: i18next.t('main:languageDropdown.translatedFraction', { + fraction: Math.round(galleryItemsTranslated[lang] * 100) + '%' + }) + }), + }; + }), + imgUrl: rootUrl + '/img', + thirdpartyUrl: rootUrl + '/thirdparty', + homeUrl: rootUrl + urlMaps[lang]['/home'], + aboutUrl: rootUrl + urlMaps[lang]['/about'], + galleryUrl: rootUrl + urlMaps[lang]['/gallery'], + simulatorUrl: rootUrl + urlMaps[lang]['/simulator'], + isHome: false, + isGallery: true, + isAbout: false, + categories: galleryList.map(item => { + return { + id: item.id, + title: i18next.t('gallery:galleryPage.categories.' + galleryCategoryToCamelCase[item.id]), + items: item.content.map(contentItem => { + return { + id: contentItem.id, + title: i18next.t('gallery:galleryData.' + galleryIDToCamelCase[contentItem.id] + '.title'), + url: rootUrl + urlMaps[lang]['/gallery/' + contentItem.id], + contributors: contentItem.contributors.join(', '), + }; + }), + }; + }), + } + fs.writeFileSync(path.join(galleryDir, 'index.html'), galleryTemplate(galleryData)); + + // Load the gallery item template + const galleryItemTemplate = Handlebars.compile(fs.readFileSync(path.join(__dirname, '../src/webpages/galleryItem.hbs'), 'utf8')); + + // Create the gallery item webpages + for (const id of galleryIDs) { + if (!galleryItemsLangs[id].includes(lang)) continue; + if (!galleryIDInList[id]) continue; + + const galleryItemData = { + title: i18next.t('gallery:galleryData.' + galleryIDToCamelCase[id] + '.title') + ' - ' + i18next.t('main:project.name'), + ogImage: rootAbsUrl + urlMaps[lang]['/gallery/' + id] + '.jpg', + absUrl: rootAbsUrl + urlMaps[lang]['/gallery/' + id], + lang: lang, + langName: langNames[lang], + supportedLangs: galleryItemsLangs[id].map((lang) => { + return { + lang: lang, + name: langNames[lang], + url: rootUrl + urlMaps[lang]['/gallery/' + id], + absUrl: rootAbsUrl + urlMaps[lang]['/gallery/' + id], + }; + }), + imgUrl: rootUrl + '/img', + thirdpartyUrl: rootUrl + '/thirdparty', + homeUrl: rootUrl + urlMaps[lang]['/home'], + aboutUrl: rootUrl + urlMaps[lang]['/about'], + galleryUrl: rootUrl + urlMaps[lang]['/gallery'], + simulatorUrl: rootUrl + urlMaps[lang]['/simulator'], + isHome: false, + isGallery: true, + isAbout: false, + id: id, + titleKey: 'gallery:galleryData.' + galleryIDToCamelCase[id] + '.title', + descriptionKey: 'gallery:galleryData.' + galleryIDToCamelCase[id] + '.description', + idHashUrl: (lang == 'en' ? '' : '..' + routesData[lang] + '/gallery/') + id, + contributors: galleryIDContributors[id].join(', '), + contributorCount: galleryIDContributors[id].length, + } + fs.writeFileSync(path.join(galleryDir, id + '.html'), galleryItemTemplate(galleryItemData)); + } + } + + // Create the modules webpage + if (modulesLangs.includes(lang)) { + // create the modules/ directory + const modulesDir = path.join(langDir, 'modules'); + fs.mkdirSync(modulesDir, { recursive: true }); + const rootUrl = lang == 'en' ? '..' : '../..'; + + // Load the modules template + const modulesTemplate = Handlebars.compile(fs.readFileSync(path.join(__dirname, '../src/webpages/modules.hbs'), 'utf8')); + const modulePageData = { + lang: lang, + langName: langNames[lang], + imgUrl: rootUrl + '/img', + thirdpartyUrl: rootUrl + '/thirdparty', + content: moduleList[0].content.map(item => { + return { + id: item.id, + thumbnailUrl: rootUrl + '/modules/' + item.id + '-thumbnail', + titleKey: 'modules:moduleData.' + item.id + '.title', + contributors: item.contributors.join(', '), + descriptionKey: 'modules:moduleData.' + item.id + '.description', + controlPointSequenceKeys: moduleControlPointSequenceKeys[item.id].map(key => 'modules:moduleData.' + item.id + '.' + key), + parametersKeys: moduleParametersKeys[item.id].map(key => 'modules:moduleData.' + item.id + '.' + key), + }; + }), + } + fs.writeFileSync(path.join(modulesDir, 'modules.html'), modulesTemplate(modulePageData)); + + // Create the module tutorial webpage + if (moduleTutorialLangs.includes(lang)) { + const moduleTutorialTemplate = Handlebars.compile(fs.readFileSync(path.join(__dirname, '../src/webpages/moduleTutorial.hbs'), 'utf8')); + + const galleryHashUrl = lang == 'en' ? '' : '..' + routesData[lang] + '/gallery/'; + const moduleTutorialData = { + title: i18next.t('modules:moduleTutorial.title') + ' - ' + i18next.t('main:project.name'), + ogImage: rootAbsUrl + '/img/image.png', + absUrl: rootAbsUrl + urlMaps[lang]['/modules/tutorial'], + lang: lang, + langName: langNames[lang], + supportedLangs: moduleTutorialLangs.map((lang) => { + return { + lang: lang, + name: langNames[lang], + url: rootUrl + urlMaps[lang]['/modules/tutorial'], + absUrl: rootAbsUrl + urlMaps[lang]['/modules/tutorial'], + }; + }), + imgUrl: rootUrl + '/img', + thirdpartyUrl: rootUrl + '/thirdparty', + homeUrl: rootUrl + urlMaps[lang]['/home'], + aboutUrl: rootUrl + urlMaps[lang]['/about'], + galleryUrl: rootUrl + urlMaps[lang]['/gallery'], + simulatorUrl: rootUrl + urlMaps[lang]['/simulator'], + isHome: false, + isGallery: false, + isAbout: false, + moduleExampleBasicsHashUrl: (galleryItemsLangs['module-example-basics'].includes(lang) ? galleryHashUrl : '') + 'module-example-basics', + moduleExampleParametersHashUrl: (galleryItemsLangs['module-example-parameters'].includes(lang) ? galleryHashUrl : '') + 'module-example-parameters', + moduleExampleControlPointsHashUrl: (galleryItemsLangs['module-example-control-points'].includes(lang) ? galleryHashUrl : '') + 'module-example-control-points', + moduleExampleArraysAndConditionalsHashUrl: (galleryItemsLangs['module-example-arrays-and-conditionals'].includes(lang) ? galleryHashUrl : '') + 'module-example-arrays-and-conditionals', + moduleExampleCustomEquationHashUrl: (galleryItemsLangs['module-example-custom-equation'].includes(lang) ? galleryHashUrl : '') + 'module-example-custom-equation', + moduleExampleShapeParametrizationHashUrl: (galleryItemsLangs['module-example-shape-parametrization'].includes(lang) ? galleryHashUrl : '') + 'module-example-shape-parametrization', + } + fs.writeFileSync(path.join(modulesDir, 'tutorial.html'), moduleTutorialTemplate(moduleTutorialData)); + } + } +} diff --git a/scripts/sortTranslations.mjs b/scripts/sortTranslations.mjs new file mode 100644 index 00000000..cc2694ba --- /dev/null +++ b/scripts/sortTranslations.mjs @@ -0,0 +1,126 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + + +// Convert import.meta.url to a file path and determine the directory +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Load the gallery data. +const galleryList = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/galleryList.json'), 'utf8')); + +// Load the module data. +const moduleList = JSON.parse(fs.readFileSync(path.join(__dirname, '../data/moduleList.json'), 'utf8')); + +// Load the English strings for the gallery. +const galleryStrings = JSON.parse(fs.readFileSync(path.join(__dirname, '../locales/en/gallery.json'), 'utf8')); + +// Load the English strings for the modules. +const moduleStrings = JSON.parse(fs.readFileSync(path.join(__dirname, '../locales/en/modules.json'), 'utf8')); + +// Sort the gallery strings by the order in the gallery list. +const galleryData = galleryStrings.galleryData; +const newGalleryData = { common: galleryData.common }; +for (const category of galleryList) { + for (const item of category.content) { + const idCamelCase = item.id.toLowerCase().replace(/-([a-z])/g, (g) => g[1].toUpperCase()); + if (galleryData[idCamelCase]) { + newGalleryData[idCamelCase] = galleryData[idCamelCase]; + } + } +} + +// Add the items in galleryData but not in galleryList. +for (const id in galleryData) { + if (!newGalleryData[id]) { + newGalleryData[id] = galleryData[id]; + } +} + +galleryStrings.galleryData = newGalleryData; + +// Sort the module strings by the order in the module list. +const moduleData = moduleStrings.moduleData; +const newModuleData = {}; +for (const module of moduleList) { + const idCamelCase = module.id.toLowerCase().replace(/-([a-z])/g, (g) => g[1].toUpperCase()); + if (moduleData[idCamelCase]) { + newModuleData[idCamelCase] = moduleData[idCamelCase]; + } +} + +// Add the items in moduleData but not in moduleList. +for (const id in moduleData) { + if (!newModuleData[id]) { + newModuleData[id] = moduleData[id]; + } +} + +moduleStrings.moduleData = newModuleData; + +// Write the sorted gallery strings to the gallery file. +fs.writeFileSync(path.join(__dirname, '../locales/en/gallery.json'), JSON.stringify(galleryStrings, null, 2)); + +// Write the sorted module strings to the module file. +fs.writeFileSync(path.join(__dirname, '../locales/en/modules.json'), JSON.stringify(moduleStrings, null, 2)); + + +// Sort the keys in other languages according to the English strings. +// List all existing languages, which are the directories in the /locales directory. +const langs = fs.readdirSync(path.join(__dirname, '../locales')).filter((file) => !file.includes('.')); + +// List all existing namespaces, which are the json files in the /locales/en directory. +const namespaces = fs.readdirSync(path.join(__dirname, '../locales/en')).filter((file) => file.endsWith('.json')); + +// Define the recursive function to sort the keys in the JSON object from the corresponding English object. Some keys are in the format {{key}}_{{suffix}}, which should be treated as a single key {{key}}. The suffix is for grammatical inflection. The relative order of the keys with the same {{key}} should not be changed. +function sortKeys(obj, enObj) { + const newObj = {}; + const keyRoots = []; + for (const key in enObj) { + const keyRoot = key.replace(/_.*$/, ''); + if (!keyRoots.includes(keyRoot)) { + keyRoots.push(keyRoot); + } + } + + for (const keyRoot of keyRoots) { + const keys = []; + for (const key in obj) { + const keyRoot2 = key.replace(/_.*$/, ''); + if (keyRoot2 === keyRoot) { + keys.push(key); + } + } + + for (const key of keys) { + if (typeof obj[key] !== 'object') { + newObj[key] = obj[key]; + } else { + newObj[key] = sortKeys(obj[key], enObj[key]); + } + } + } + + return newObj; +} + +// Sort the keys in the JSON files for each language for each namespace. +for (const namespace of namespaces) { + const enObj = JSON.parse(fs.readFileSync(path.join(__dirname, '../locales/en', namespace), 'utf8')); + for (const lang of langs) { + if (lang === 'en') { + continue; + } + + // Load the JSON object for the language, which may not exist. + const langPath = path.join(__dirname, '../locales', lang, namespace); + if (!fs.existsSync(langPath)) { + continue; + } + + const langObj = JSON.parse(fs.readFileSync(langPath, 'utf8')); + const newLangObj = sortKeys(langObj, enObj); + fs.writeFileSync(langPath, JSON.stringify(newLangObj, null, 2)); + } +} \ No newline at end of file diff --git a/scripts/syncTranslations.js b/scripts/syncTranslations.js deleted file mode 100644 index 486ee1c0..00000000 --- a/scripts/syncTranslations.js +++ /dev/null @@ -1,32 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -function syncTranslations(localeDir) { - const enContent = JSON.parse(fs.readFileSync(path.join(localeDir, 'en.json'), 'utf8')); - const files = fs.readdirSync(localeDir); - - files.forEach(file => { - if (path.extname(file) === '.json' && file !== 'en.json' && file !== 'completeness.json') { - const content = JSON.parse(fs.readFileSync(path.join(localeDir, file), 'utf8')); - const newContent = {}; - for (const key in enContent) { - if (content[key]) { - if (content[key].incomplete) { - newContent[key] = { incomplete: true, message: enContent[key].message }; - } else { - newContent[key] = { message: content[key].message }; - } - } else { - newContent[key] = { incomplete: true, message: enContent[key].message }; - } - } - fs.writeFileSync(path.join(localeDir, file), JSON.stringify(newContent, null, 2)); - } - }); -} - - -const localeDir = path.join(__dirname, '../locales'); - -syncTranslations(localeDir); -console.log('Translations synchronized.'); diff --git a/src/img/1.png b/src/img/1.png deleted file mode 100644 index aa85d0b9..00000000 Binary files a/src/img/1.png and /dev/null differ diff --git a/src/img/1.svg b/src/img/1.svg deleted file mode 100644 index 75d40089..00000000 --- a/src/img/1.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/img/2.svg b/src/img/2.svg deleted file mode 100644 index 86162954..00000000 --- a/src/img/2.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/img/3.svg b/src/img/3.svg deleted file mode 100644 index 0ae2bb2b..00000000 --- a/src/img/3.svg +++ /dev/null @@ -1 +0,0 @@ -0100200300400500600ObjectiveEyepieceObjectiveEyepiece diff --git a/src/img/5.svg b/src/img/5.svg deleted file mode 100644 index 6f9e3854..00000000 --- a/src/img/5.svg +++ /dev/null @@ -1 +0,0 @@ -0100200Observed image (orange)ObserverObject underwater (green)Observed image (orange)ObserverObject underwater (green) diff --git a/src/img/6.png b/src/img/6.png deleted file mode 100644 index 51bb61d1..00000000 Binary files a/src/img/6.png and /dev/null differ diff --git a/src/img/4.svg b/src/img/images-formed-by-two-mirrors.svg similarity index 100% rename from src/img/4.svg rename to src/img/images-formed-by-two-mirrors.svg diff --git a/src/img/1.jpg b/src/img/spherical-lens-and-mirror.jpg similarity index 100% rename from src/img/1.jpg rename to src/img/spherical-lens-and-mirror.jpg diff --git a/src/simulator/index.html b/src/simulator/index.html index 1c641399..f7213c9e 100644 --- a/src/simulator/index.html +++ b/src/simulator/index.html @@ -7,7 +7,7 @@ - + @@ -29,84 +29,53 @@
- Welcome to Ray Optics Simulation
To add an optical component, select a tool and click the blank space.
To load an example, please go to the Gallery page. +
Welcome to Ray Optics Simulation
+
You need to enable JavaScript to run this app.
+
@@ -137,7 +106,7 @@ -
+
-
-
+
-
-
+
-
+
-
+
-
-
+
@@ -434,8 +403,8 @@