From b1c89fa6e7d7e5799f7934639cd28e8fa0a4605f Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 8 Apr 2024 22:15:16 +0800 Subject: [PATCH 1/5] feat: support i18n --- package-lock.json | 39 ++++++- package.json | 1 + source/engine/import/importerbim.js | 4 +- source/engine/import/importergltf.js | 10 +- source/website/dialogs.js | 4 +- source/website/exportdialog.js | 20 ++-- source/website/i18next.js | 27 +++++ source/website/locale/zh-CN.json | 128 ++++++++++++++++++++++ source/website/measuretool.js | 12 +- source/website/navigatorfilespanel.js | 8 +- source/website/navigatormaterialspanel.js | 6 +- source/website/navigatormeshespanel.js | 16 +-- source/website/openurldialog.js | 10 +- source/website/sharingdialog.js | 16 +-- source/website/sidebardetailspanel.js | 70 ++++++------ source/website/sidebarsettingspanel.js | 24 ++-- source/website/snapshotdialog.js | 22 ++-- source/website/threemodelloaderui.js | 24 ++-- source/website/utils.js | 8 +- source/website/website.js | 46 ++++---- website/index.html | 4 +- 21 files changed, 357 insertions(+), 142 deletions(-) create mode 100644 source/website/i18next.js create mode 100644 source/website/locale/zh-CN.json diff --git a/package-lock.json b/package-lock.json index 03450f0b..8384d5b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@simonwep/pickr": "1.9.0", "draco3d": "1.5.6", "fflate": "0.8.1", + "i18next": "23.10.1", "occt-import-js": "0.0.21", "rhino3dm": "8.0.1", "three": "0.158.0", @@ -64,7 +65,6 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.4.tgz", "integrity": "sha512-2Yv65nlWnWlSpe3fXEyX5i7fx5kIKo4Qbcj+hMO0odwaneFjfXw5fdum+4yL20O0QiaHpia0cYQ9xpNMqrBwHg==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -75,8 +75,7 @@ "node_modules/@babel/runtime/node_modules/regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", - "dev": true + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, "node_modules/@esbuild/android-arm": { "version": "0.19.6", @@ -3413,6 +3412,28 @@ "ms": "^2.0.0" } }, + "node_modules/i18next": { + "version": "23.10.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.10.1.tgz", + "integrity": "sha512-NDiIzFbcs3O9PXpfhkjyf7WdqFn5Vq6mhzhtkXzj51aOcNuPNcTwuYNuXCpHsanZGHlHKL35G7huoFeVic1hng==", + "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/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -6059,7 +6080,6 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.4.tgz", "integrity": "sha512-2Yv65nlWnWlSpe3fXEyX5i7fx5kIKo4Qbcj+hMO0odwaneFjfXw5fdum+4yL20O0QiaHpia0cYQ9xpNMqrBwHg==", - "dev": true, "requires": { "regenerator-runtime": "^0.14.0" }, @@ -6067,8 +6087,7 @@ "regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", - "dev": true + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" } } }, @@ -8433,6 +8452,14 @@ "ms": "^2.0.0" } }, + "i18next": { + "version": "23.10.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.10.1.tgz", + "integrity": "sha512-NDiIzFbcs3O9PXpfhkjyf7WdqFn5Vq6mhzhtkXzj51aOcNuPNcTwuYNuXCpHsanZGHlHKL35G7huoFeVic1hng==", + "requires": { + "@babel/runtime": "^7.23.2" + } + }, "iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", diff --git a/package.json b/package.json index 69bf3205..01f5c473 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "@simonwep/pickr": "1.9.0", "draco3d": "1.5.6", "fflate": "0.8.1", + "i18next": "23.10.1", "occt-import-js": "0.0.21", "rhino3dm": "8.0.1", "three": "0.158.0", diff --git a/source/engine/import/importerbim.js b/source/engine/import/importerbim.js index 48103df2..f415ec17 100644 --- a/source/engine/import/importerbim.js +++ b/source/engine/import/importerbim.js @@ -13,6 +13,8 @@ import { ColorToMaterialConverter } from './importerutils.js'; import { Property, PropertyGroup, PropertyType } from '../model/property.js'; import { Unit } from '../model/unit.js'; +import { t } from '../../website/i18next.js'; + export class ImporterBim extends ImporterBase { constructor () @@ -170,7 +172,7 @@ export class ImporterBim extends ImporterBase } let info = source.info; - let propertyGroup = new PropertyGroup ('Info'); + let propertyGroup = new PropertyGroup (t('Info')); AddProperty (propertyGroup, 'Guid', source.guid); AddProperty (propertyGroup, 'Type', source.type); for (let propertyName in info) { diff --git a/source/engine/import/importergltf.js b/source/engine/import/importergltf.js index 54b19b0a..77dd0b60 100644 --- a/source/engine/import/importergltf.js +++ b/source/engine/import/importergltf.js @@ -16,6 +16,8 @@ import { Property, PropertyGroup, PropertyType } from '../model/property.js'; import { Triangle } from '../model/triangle.js'; import { ImporterBase } from './importerbase.js'; +import { t } from '../../website/i18next.js'; + const GltfComponentType = { BYTE : 5120, @@ -641,7 +643,7 @@ export class ImporterGltf extends ImporterBase } } - this.ImportProperties (this.model, gltf.asset, 'Asset properties'); + this.ImportProperties (this.model, gltf.asset, t('Asset properties')); this.ImportScene (gltf); } @@ -809,7 +811,7 @@ export class ImporterGltf extends ImporterBase this.ImportPrimitive (gltf, primitive, mesh); } - this.ImportProperties (mesh, gltfMesh.extras, 'Mesh properties'); + this.ImportProperties (mesh, gltfMesh.extras, t('Mesh properties')); } ImportPrimitive (gltf, primitive, mesh) @@ -1006,7 +1008,7 @@ export class ImporterGltf extends ImporterBase this.ImportNode (gltf, gltfNode, rootNode); } - this.ImportProperties (this.model, scene.extras, 'Scene properties'); + this.ImportProperties (this.model, scene.extras, t('Scene properties')); } ImportNode (gltf, gltfNode, parentNode) @@ -1058,7 +1060,7 @@ export class ImporterGltf extends ImporterBase if (gltfNode.mesh !== undefined) { let mesh = this.model.GetMesh (gltfNode.mesh); - this.ImportProperties (mesh, gltfNode.extras, 'Node properties'); + this.ImportProperties (mesh, gltfNode.extras, t('Node properties')); node.AddMeshIndex (gltfNode.mesh); } } diff --git a/source/website/dialogs.js b/source/website/dialogs.js index 602de83c..5e7dcbb7 100644 --- a/source/website/dialogs.js +++ b/source/website/dialogs.js @@ -1,12 +1,14 @@ import { AddDiv } from '../engine/viewer/domutils.js'; import { ButtonDialog, ListPopup } from './dialog.js'; +import { t } from './i18next.js'; + export function ShowMessageDialog (title, message, subMessage) { let dialog = new ButtonDialog (); let contentDiv = dialog.Init (title, [ { - name : 'OK', + name : t('OK'), onClick () { dialog.Close (); } diff --git a/source/website/exportdialog.js b/source/website/exportdialog.js index 65cd15d3..f90d5efe 100644 --- a/source/website/exportdialog.js +++ b/source/website/exportdialog.js @@ -12,6 +12,8 @@ import { DownloadArrayBufferAsFile } from './utils.js'; import { CookieGetStringVal, CookieSetStringVal } from './cookiehandler.js'; import { HandleEvent } from './eventhandler.js'; +import { t } from './i18next.js'; + import * as fflate from 'fflate'; function AddSelectWithCookieSave (parentElement, cookieKey, options, defaultSelectedIndex, onChange) @@ -53,8 +55,8 @@ class ModelExporterUI return AddSelectWithCookieSave (parameterValueDiv, cookieKey, values, defaultIndex); } - this.visibleOnlySelect = AddSelectItem (parametersDiv, 'Scope', 'ov_last_scope', ['Entire Model', 'Visible Only'], 1); - this.rotationSelect = AddSelectItem (parametersDiv, 'Rotation', 'ov_last_rotation', ['No Rotation', '-90 Degrees', '90 Degrees'], 0); + this.visibleOnlySelect = AddSelectItem (parametersDiv, t('Scope'), 'ov_last_scope', [t('Entire Model'), t('Visible Only')], 1); + this.rotationSelect = AddSelectItem (parametersDiv, t('Rotation'), 'ov_last_rotation', [t('No Rotation'), t('-90 Degrees'), t('90 Degrees')], 0); } ExportModel (model, callbacks) @@ -77,15 +79,15 @@ class ModelExporterUI let exporterModel = new ExporterModel (model, settings); if (exporterModel.MeshInstanceCount () === 0) { ShowMessageDialog ( - 'Export Failed', - 'The model doesn\'t contain any meshes.', + t('Export Failed'), + t('The model doesn\'t contain any meshes.'), null ); return; } let progressDialog = new ProgressDialog (); - progressDialog.Init ('Exporting Model'); + progressDialog.Init (t('Exporting Model')); progressDialog.Open (); RunTaskAsync (() => { @@ -142,16 +144,16 @@ class ExportDialog Open (model, viewer) { let mainDialog = new ButtonDialog (); - let contentDiv = mainDialog.Init ('Export', [ + let contentDiv = mainDialog.Init (t('Export'), [ { - name : 'Close', + name : t('Close'), subClass : 'outline', onClick () { mainDialog.Close (); } }, { - name : 'Export', + name : t('Export'), onClick : () => { mainDialog.Close (); this.ExportFormat (model, viewer); @@ -159,7 +161,7 @@ class ExportDialog } ]); - let text = 'Select the format from the list below, and adjust the settings of the selected format.'; + let text = t('Select the format from the list below, and adjust the settings of the selected format.'); AddDiv (contentDiv, 'ov_dialog_section', text); let formatRow = AddDiv (contentDiv, 'ov_dialog_row'); diff --git a/source/website/i18next.js b/source/website/i18next.js new file mode 100644 index 00000000..aff18b9d --- /dev/null +++ b/source/website/i18next.js @@ -0,0 +1,27 @@ +import i18next from 'i18next'; +import { CookieGetStringVal } from './cookiehandler.js'; + +import zhCN from './locale/zh-CN.json'; + +const defaultLang = CookieGetStringVal('ov_language', navigator.language); + +i18next.init({ + lng: defaultLang, // if you're u sing a language detector, do not define the lng option + debug: false, + supportedLngs: ['zh-CN'], + resources: { + 'zh-CN': { translation: zhCN }, + }, +}); + +const t = i18next.t; + +export { i18next, t }; + +// translate HTML +document.addEventListener('DOMContentLoaded', () => { + document.querySelectorAll('[data-i18n]').forEach((ele) => { + const translateKey = ele.getAttribute('data-i18n') || ele.textContent; + ele.textContent = t(translateKey); + }); +}); diff --git a/source/website/locale/zh-CN.json b/source/website/locale/zh-CN.json new file mode 100644 index 00000000..c9bf122d --- /dev/null +++ b/source/website/locale/zh-CN.json @@ -0,0 +1,128 @@ +{ + "Drag and drop 3D models here.": "拖拽3D模型到这里", + "Check an example file:": "查看示例文件:", + "Fit model to window": "自适应窗口", + "Set Y axis as up vector": "Y轴向上", + "Set Z axis as up vector": "Z轴向上", + "Flip up vector": "上下翻转", + "Fixed up vector": "固定移动", + "Free orbit": "自由移动", + "Perspective camera": "透视相机", + "Orthographic camera": "正交相机", + "Files": "文件", + "Materials": "材质", + "Meshes": "网格", + "Details": "详情", + "Calculate": "计算", + "Model Display": "模型显示设置", + "Background Color": "背景颜色", + "Show Edges": "显示边缘", + "Edge Color": "边缘颜色", + "Edge Angle Threshold": "边角阈值", + "Reset to Default": "恢复默认设置", + "Importing Model": "模型导入中...", + "Visualizing Model": "模型渲染中...", + "Something went wrong": "出错了!", + "No importable file found.": "无法加载要导入的文件", + "Failed to load file for import.": "无法加载要导入的文件", + "The remote server refused to fulfill the request. Check if the url is correct, and make sure that CORS requests are allowed on the remote server.": "远程服务器拒绝完成请求。请检查模型url是否正确,并确保远程服务器上允许 CORS 请求。", + "Failed to import model.": "模型载入失败", + "Unknown error.": "未知错误", + "OK": "确定", + "Cancel": "取消", + "Close": "关闭", + "Create": "创建", + "Settings": "设置", + "Light mode": "明亮模式", + "Dark mode": "暗黑模式", + "Import Settings": "导入设置", + "Default Color": "默认颜色", + "Default Line Color": "默认线条颜色", + "Background Image": "背景图片", + "No Name": "未命名", + "Info": "信息", + "Missing Files": "缺失的文件", + "Available Files": "可用的文件", + "Open from your device": "从设备中打开", + "Open from url": "从url中打开", + "Here you can load models based on their urls. You can add more lines if your model builds up from multiple files.": "在这里,您可以根据url加载模型。如果您的模型由多个文件组成,您可以添加多行。", + "Measure": "测量", + "Download": "下载", + "Export": "导出", + "Share": "分享", + "Create snapshot": "创建快照", + "Flat list": "列表视图", + "Tree view": "树形视图", + "Expand all": "展开全部", + "Collapse all": "折叠全部", + "Show/hide meshes": "显示/隐藏网格", + "Fit meshes to window": "网格适应窗口", + "Create Snapshot": "创建快照", + "Small": "小", + "Medium": "中", + "Large": "大", + "Custom": "自定义", + "Width": "宽", + "Height": "高", + "Transparent background": "透明背景", + "Sharing Link": "分享链接", + "Embedding Code": "嵌入代码", + "Use customized settings": "使用自定义设置", + "Copy": "复制", + "Copied": "已复制", + "Select the format from the list below, and adjust the settings of the selected format.": "从下面的列表中选择格式,并调整所选格式的设置。", + "Export Failed": "导出失败", + "The model doesn\\'t contain any meshes.": "模型不包含任何网格。", + "Exporting Model": "模型导出中", + "Scope": "范围", + "Rotation": "旋转", + "Entire Model": "整个模型", + "Visible Only": "仅可见部分", + "No Rotation": "无旋转", + "-90 Degrees": "-90度", + "90 Degrees": "90度", + "Select a point.": "选择一个点", + "Select another point.": "选择另一个点", + "Distance of points": "两点之间的距离", + "Distance of parallel faces": "平行面之间的距离", + "Angle of faces": "面之间的角度", + "Cookies Policy": "Cookies政策", + "This website uses cookies to offer you better user experience. See the details at the {{- link }} page.": "本网站使用cookies为您提供更好的用户体验。请查看{{- link }}页面的详细信息。", + "Accept": "接受", + "Vertices": "点", + "Lines": "线", + "Triangles": "三角形", + "Unit": "单位", + "Millimeter": "毫米", + "Centimeter": "厘米", + "Meter": "米", + "Inch": "英寸", + "Foot": "英尺", + "Size X": "尺寸 X", + "Size Y": "尺寸 Y", + "Size Z": "尺寸 Z", + "Volume": "体积", + "Surface": "表面积", + "Unknown": "未知", + "Asset properties": "资源属性", + "Mesh properties": "网格属性", + "Scene properties": "场景属性", + "Node properties": "节点属性", + "Default": "默认", + "Model": "来自模型", + "Source": "来源", + "Type": "类型", + "Color": "颜色", + "Ambient": "环境光", + "Specular": "高光", + "Metalness": "金属度", + "Roughness": "粗糙度", + "Opacity": "透明度", + "Diffuse Map": "漫反射贴图", + "Bump Map": "凹凸贴图", + "Normal Map": "法线贴图", + "Emissive Map": "自发光贴图", + "Specular Map": "高光贴图", + "Metallic Map": "金属贴图", + "Please wait...": "请稍等..." +} diff --git a/source/website/measuretool.js b/source/website/measuretool.js index 73426084..cbe6f91e 100644 --- a/source/website/measuretool.js +++ b/source/website/measuretool.js @@ -6,6 +6,8 @@ import * as THREE from 'three'; import { ColorComponentToFloat, RGBColor } from '../engine/model/color.js'; import { IntersectionMode } from '../engine/viewer/viewermodel.js'; +import { t } from './i18next.js'; + function GetFaceWorldNormal (intersection) { let normalMatrix = new THREE.Matrix4 (); @@ -231,21 +233,21 @@ export class MeasureTool this.panel.style.backgroundColor = 'transparent'; } if (this.markers.length === 0) { - this.panel.innerHTML = 'Select a point.'; + this.panel.innerHTML = t('Select a point.'); } else if (this.markers.length === 1) { - this.panel.innerHTML = 'Select another point.'; + this.panel.innerHTML = t('Select another point.'); } else { let calcResult = CalculateMarkerValues (this.markers[0], this.markers[1]); if (calcResult.pointsDistance !== null) { - AddValue (this.panel, 'measure_distance', 'Distance of points', calcResult.pointsDistance.toFixed (3)); + AddValue (this.panel, 'measure_distance', t('Distance of points'), calcResult.pointsDistance.toFixed (3)); } if (calcResult.parallelFacesDistance !== null) { - AddValue (this.panel, 'measure_distance_parallel', 'Distance of parallel faces', calcResult.parallelFacesDistance.toFixed (3)); + AddValue (this.panel, 'measure_distance_parallel', t('Distance of parallel faces'), calcResult.parallelFacesDistance.toFixed (3)); } if (calcResult.facesAngle !== null) { let degreeValue = calcResult.facesAngle * RadDeg; - AddValue (this.panel, 'measure_angle', 'Angle of faces', degreeValue.toFixed (1) + '\xB0'); + AddValue (this.panel, 'measure_angle', t('Angle of faces'), degreeValue.toFixed (1) + '\xB0'); } } this.Resize (); diff --git a/source/website/navigatorfilespanel.js b/source/website/navigatorfilespanel.js index 4879c8e8..49780d30 100644 --- a/source/website/navigatorfilespanel.js +++ b/source/website/navigatorfilespanel.js @@ -2,6 +2,8 @@ import { SetDomElementHeight, GetDomElementOuterHeight } from '../engine/viewer/ import { NavigatorPanel } from './navigatorpanel.js'; import { TreeViewButton, TreeViewButtonItem, TreeViewGroupItem, TreeViewSingleItem } from './treeview.js'; +import { t } from './i18next.js'; + export class NavigatorFilesPanel extends NavigatorPanel { constructor (parentDiv) @@ -11,7 +13,7 @@ export class NavigatorFilesPanel extends NavigatorPanel GetName () { - return 'Files'; + return t('Files'); } GetIcon () @@ -38,7 +40,7 @@ export class NavigatorFilesPanel extends NavigatorPanel const missingFiles = importResult.missingFiles; if (missingFiles.length > 0) { - let missingFilesItem = new TreeViewGroupItem ('Missing Files', null); + let missingFilesItem = new TreeViewGroupItem (t('Missing Files'), null); missingFilesItem.ShowChildren (true); this.treeView.AddChild (missingFilesItem); for (let i = 0; i < missingFiles.length; i++) { @@ -51,7 +53,7 @@ export class NavigatorFilesPanel extends NavigatorPanel item.AppendButton (browseButton); missingFilesItem.AddChild (item); } - let filesItem = new TreeViewGroupItem ('Available Files', null); + let filesItem = new TreeViewGroupItem (t('Available Files'), null); filesItem.ShowChildren (true); this.treeView.AddChild (filesItem); for (let i = 0; i < usedFiles.length; i++) { diff --git a/source/website/navigatormaterialspanel.js b/source/website/navigatormaterialspanel.js index ea33f80e..d687c07b 100644 --- a/source/website/navigatormaterialspanel.js +++ b/source/website/navigatormaterialspanel.js @@ -4,6 +4,8 @@ import { MaterialItem } from './navigatoritems.js'; import { NavigatorPanel, NavigatorPopupButton } from './navigatorpanel.js'; import { GetMaterialName, GetMeshName } from './utils.js'; +import {t} from './i18next.js'; + class NavigatorMeshesPopupButton extends NavigatorPopupButton { constructor (parentDiv) @@ -19,7 +21,7 @@ class NavigatorMeshesPopupButton extends NavigatorPopupButton return; } - let meshesText = 'Meshes (' + this.meshInstanceArray.length + ')'; + let meshesText = t('Meshes') + ' (' + this.meshInstanceArray.length + ')'; this.buttonText.innerHTML = meshesText; } @@ -74,7 +76,7 @@ export class NavigatorMaterialsPanel extends NavigatorPanel GetName () { - return 'Materials'; + return t('Materials'); } GetIcon () diff --git a/source/website/navigatormeshespanel.js b/source/website/navigatormeshespanel.js index 19303380..9673cb50 100644 --- a/source/website/navigatormeshespanel.js +++ b/source/website/navigatormeshespanel.js @@ -5,6 +5,8 @@ import { MeshItem, NavigatorItemRecurse, NodeItem } from './navigatoritems.js'; import { NavigatorPanel, NavigatorPopupButton } from './navigatorpanel.js'; import { AddSvgIconElement, GetMaterialName, GetMeshName, GetNodeName, SetSvgIconImageElement } from './utils.js'; +import { t } from './i18next.js'; + const MeshesPanelMode = { Simple : 0, @@ -86,7 +88,7 @@ export class NavigatorMeshesPanel extends NavigatorPanel GetName () { - return 'Meshes'; + return t('Meshes'); } GetIcon () @@ -228,38 +230,38 @@ export class NavigatorMeshesPanel extends NavigatorPanel this.buttons = { flatList : { - name : 'Flat list', + name : t('Flat list'), icon : 'flat_list', div : null, iconDiv : null }, treeView : { - name : 'Tree view', + name : t('Tree view'), icon : 'tree_view', div : null, iconDiv : null }, separator : null, expandAll : { - name : 'Expand all', + name : t('Expand all'), icon : 'expand', div : null, iconDiv : null }, collapseAll : { - name : 'Collapse all', + name : t('Collapse all'), icon : 'collapse', div : null, iconDiv : null }, showHideMeshes : { - name : 'Show/hide meshes', + name : t('Show/hide meshes'), icon : 'visible', div : null, iconDiv : null }, fitToWindow : { - name : 'Fit meshes to window', + name : t('Fit meshes to window'), icon : 'fit', div : null, iconDiv : null diff --git a/source/website/openurldialog.js b/source/website/openurldialog.js index ca5aa2c6..fd071225 100644 --- a/source/website/openurldialog.js +++ b/source/website/openurldialog.js @@ -2,20 +2,22 @@ import { ReadLines } from '../engine/import/importerutils.js'; import { AddDiv, CreateDomElement } from '../engine/viewer/domutils.js'; import { ButtonDialog } from './dialog.js'; +import { t } from './i18next.js'; + export function ShowOpenUrlDialog (onOk) { let dialog = new ButtonDialog (); let urlsTextArea = CreateDomElement ('textarea', 'ov_dialog_textarea'); - let contentDiv = dialog.Init ('Open from url', [ + let contentDiv = dialog.Init (t('Open from url'), [ { - name : 'Cancel', + name : t('Cancel'), subClass : 'outline', onClick () { dialog.Close (); } }, { - name : 'OK', + name : t('OK'), onClick () { let urls = []; ReadLines (urlsTextArea.value, (line) => { @@ -26,7 +28,7 @@ export function ShowOpenUrlDialog (onOk) } } ]); - let text = 'Here you can load models based on their urls. You can add more lines if your model builds up from multiple files.'; + let text = t('Here you can load models based on their urls. You can add more lines if your model builds up from multiple files.'); AddDiv (contentDiv, 'ov_dialog_section', text); contentDiv.appendChild (urlsTextArea); dialog.Open (); diff --git a/source/website/sharingdialog.js b/source/website/sharingdialog.js index db96a7ff..25558ed7 100644 --- a/source/website/sharingdialog.js +++ b/source/website/sharingdialog.js @@ -7,6 +7,8 @@ import { ButtonDialog } from './dialog.js'; import { CopyToClipboard } from './utils.js'; import { HandleEvent } from './eventhandler.js'; +import { t } from './i18next.js'; + export function ShowSharingDialog (fileList, settings, viewer) { function AddCheckboxLine (parentDiv, text, id, onChange) @@ -19,8 +21,8 @@ export function ShowSharingDialog (fileList, settings, viewer) function AddCopyableTextInput (parentDiv, getText) { - let copyText = 'Copy'; - let copiedText = 'Copied'; + let copyText = t('Copy'); + let copiedText = t('Copied'); let container = AddDiv (parentDiv, 'ov_dialog_copyable_input'); let input = AddDomElement (container, 'input', null); input.setAttribute ('type', 'text'); @@ -47,7 +49,7 @@ export function ShowSharingDialog (fileList, settings, viewer) } let section = AddDiv (parentDiv, 'ov_dialog_section'); - AddDiv (section, 'ov_dialog_inner_title', 'Sharing Link'); + AddDiv (section, 'ov_dialog_inner_title', t('Sharing Link')); let sharingLinkInput = AddCopyableTextInput (section, () => { HandleEvent ('model_shared', 'sharing_link'); return GetSharingLink (modelFiles); @@ -88,13 +90,13 @@ export function ShowSharingDialog (fileList, settings, viewer) let useCurrentSettings = true; let section = AddDiv (parentDiv, 'ov_dialog_section'); section.style.marginTop = '20px'; - AddDiv (section, 'ov_dialog_inner_title', 'Embedding Code'); + AddDiv (section, 'ov_dialog_inner_title', t('Embedding Code')); let optionsSection = AddDiv (section, 'ov_dialog_section'); let embeddingCodeInput = AddCopyableTextInput (section, () => { HandleEvent ('model_shared', 'embedding_code'); return GetEmbeddingCode (modelFiles, useCurrentSettings, settings, viewer); }); - AddCheckboxLine (optionsSection, 'Use customized settings', 'embed_current_settings', (checked) => { + AddCheckboxLine (optionsSection, t('Use customized settings'), 'embed_current_settings', (checked) => { useCurrentSettings = checked; embeddingCodeInput.value = GetEmbeddingCode (modelFiles, useCurrentSettings, settings, viewer); }); @@ -120,9 +122,9 @@ export function ShowSharingDialog (fileList, settings, viewer) } let dialog = new ButtonDialog (); - let contentDiv = dialog.Init ('Share', [ + let contentDiv = dialog.Init (t('Share'), [ { - name : 'Close', + name : t('Close'), onClick () { dialog.Close (); } diff --git a/source/website/sidebardetailspanel.js b/source/website/sidebardetailspanel.js index 73211bc1..9249c9cb 100644 --- a/source/website/sidebardetailspanel.js +++ b/source/website/sidebardetailspanel.js @@ -11,21 +11,23 @@ import { MaterialSource, MaterialType } from '../engine/model/material.js'; import { RGBColorToHexString } from '../engine/model/color.js'; import { Unit } from '../engine/model/unit.js'; +import { t } from './i18next.js'; + function UnitToString (unit) { switch (unit) { case Unit.Millimeter: - return 'Millimeter'; + return t('Millimeter'); case Unit.Centimeter: - return 'Centimeter'; + return t('Centimeter'); case Unit.Meter: - return 'Meter'; + return t('Meter'); case Unit.Inch: - return 'Inch'; + return t('Inch'); case Unit.Foot: - return 'Foot'; + return t('Foot'); } - return 'Unknown'; + return t('Unknown'); } export class SidebarDetailsPanel extends SidebarPanel @@ -37,7 +39,7 @@ export class SidebarDetailsPanel extends SidebarPanel GetName () { - return 'Details'; + return t('Details'); } GetIcon () @@ -52,29 +54,29 @@ export class SidebarDetailsPanel extends SidebarPanel let boundingBox = GetBoundingBox (object3D); let size = SubCoord3D (boundingBox.max, boundingBox.min); let unit = model.GetUnit (); - this.AddProperty (table, new Property (PropertyType.Integer, 'Vertices', object3D.VertexCount ())); + this.AddProperty (table, new Property (PropertyType.Integer, t('Vertices'), object3D.VertexCount ())); let lineSegmentCount = object3D.LineSegmentCount (); if (lineSegmentCount > 0) { - this.AddProperty (table, new Property (PropertyType.Integer, 'Lines', lineSegmentCount)); + this.AddProperty (table, new Property (PropertyType.Integer, t('Lines'), lineSegmentCount)); } let triangleCount = object3D.TriangleCount (); if (triangleCount > 0) { - this.AddProperty (table, new Property (PropertyType.Integer, 'Triangles', triangleCount)); + this.AddProperty (table, new Property (PropertyType.Integer, t('Triangles'), triangleCount)); } if (unit !== Unit.Unknown) { - this.AddProperty (table, new Property (PropertyType.Text, 'Unit', UnitToString (unit))); + this.AddProperty (table, new Property (PropertyType.Text, t('Unit'), UnitToString (unit))); } - this.AddProperty (table, new Property (PropertyType.Number, 'Size X', size.x)); - this.AddProperty (table, new Property (PropertyType.Number, 'Size Y', size.y)); - this.AddProperty (table, new Property (PropertyType.Number, 'Size Z', size.z)); - this.AddCalculatedProperty (table, 'Volume', () => { + this.AddProperty (table, new Property (PropertyType.Number, t('Size X'), size.x)); + this.AddProperty (table, new Property (PropertyType.Number, t('Size Y'), size.y)); + this.AddProperty (table, new Property (PropertyType.Number, t('Size Z'), size.z)); + this.AddCalculatedProperty (table, t('Volume'), () => { if (!IsTwoManifold (object3D)) { return null; } const volume = CalculateVolume (object3D); return new Property (PropertyType.Number, null, volume); }); - this.AddCalculatedProperty (table, 'Surface', () => { + this.AddCalculatedProperty (table, t('Surface'), () => { const surfaceArea = CalculateSurfaceArea (object3D); return new Property (PropertyType.Number, null, surfaceArea); }); @@ -111,31 +113,31 @@ export class SidebarDetailsPanel extends SidebarPanel } else if (material.type === MaterialType.Physical) { typeString = 'Physical'; } - let materialSource = (material.source !== MaterialSource.Model) ? 'Default' : 'Model'; - this.AddProperty (table, new Property (PropertyType.Text, 'Source', materialSource)); - this.AddProperty (table, new Property (PropertyType.Text, 'Type', typeString)); + let materialSource = (material.source !== MaterialSource.Model) ? t('Default') : t('Model'); + this.AddProperty (table, new Property (PropertyType.Text, t('Source'), materialSource)); + this.AddProperty (table, new Property (PropertyType.Text, t('Type'), typeString)); if (material.vertexColors) { - this.AddProperty (table, new Property (PropertyType.Text, 'Color', 'Vertex colors')); + this.AddProperty (table, new Property (PropertyType.Text, t('Color'), 'Vertex colors')); } else { - this.AddProperty (table, new Property (PropertyType.Color, 'Color', material.color)); + this.AddProperty (table, new Property (PropertyType.Color, t('Color'), material.color)); if (material.type === MaterialType.Phong) { - this.AddProperty (table, new Property (PropertyType.Color, 'Ambient', material.ambient)); - this.AddProperty (table, new Property (PropertyType.Color, 'Specular', material.specular)); + this.AddProperty (table, new Property (PropertyType.Color, t('Ambient'), material.ambient)); + this.AddProperty (table, new Property (PropertyType.Color, t('Specular'), material.specular)); } } if (material.type === MaterialType.Physical) { - this.AddProperty (table, new Property (PropertyType.Percent, 'Metalness', material.metalness)); - this.AddProperty (table, new Property (PropertyType.Percent, 'Roughness', material.roughness)); + this.AddProperty (table, new Property (PropertyType.Percent, t('Metalness'), material.metalness)); + this.AddProperty (table, new Property (PropertyType.Percent, t('Roughness'), material.roughness)); } - this.AddProperty (table, new Property (PropertyType.Percent, 'Opacity', material.opacity)); - AddTextureMap (this, table, 'Diffuse Map', material.diffuseMap); - AddTextureMap (this, table, 'Bump Map', material.bumpMap); - AddTextureMap (this, table, 'Normal Map', material.normalMap); - AddTextureMap (this, table, 'Emissive Map', material.emissiveMap); + this.AddProperty (table, new Property (PropertyType.Percent, t('Opacity'), material.opacity)); + AddTextureMap (this, table, t('Diffuse Map'), material.diffuseMap); + AddTextureMap (this, table, t('Bump Map'), material.bumpMap); + AddTextureMap (this, table, t('Normal Map'), material.normalMap); + AddTextureMap (this, table, t('Emissive Map'), material.emissiveMap); if (material.type === MaterialType.Phong) { - AddTextureMap (this, table, 'Specular Map', material.specularMap); + AddTextureMap (this, table, t('Specular Map'), material.specularMap); } else if (material.type === MaterialType.Physical) { - AddTextureMap (this, table, 'Metallic Map', material.metalnessMap); + AddTextureMap (this, table, t('Metallic Map'), material.metalnessMap); } this.Resize (); } @@ -169,10 +171,10 @@ export class SidebarDetailsPanel extends SidebarPanel let valueColumn = AddDiv (row, 'ov_property_table_cell ov_property_table_value'); nameColumn.setAttribute ('title', name); - let calculateButton = AddDiv (valueColumn, 'ov_property_table_button', 'Calculate...'); + let calculateButton = AddDiv (valueColumn, 'ov_property_table_button', t('Calculate') + '...'); calculateButton.addEventListener ('click', () => { ClearDomElement (valueColumn); - valueColumn.innerHTML = 'Please wait...'; + valueColumn.innerHTML = t('Please wait...'); RunTaskAsync (() => { let propertyValue = calculateValue (); if (propertyValue === null) { diff --git a/source/website/sidebarsettingspanel.js b/source/website/sidebarsettingspanel.js index 5ed9008f..ecda03d4 100644 --- a/source/website/sidebarsettingspanel.js +++ b/source/website/sidebarsettingspanel.js @@ -12,6 +12,8 @@ import * as Pickr from '@simonwep/pickr'; import '@simonwep/pickr/dist/themes/monolith.min.css'; import { MaterialSource } from '../engine/main.js'; +import { t } from './i18next.js'; + function AddColorPicker (parentDiv, opacity, defaultColor, predefinedColors, onChange) { let pickr = Pickr.create ({ @@ -194,7 +196,7 @@ class SettingsModelDisplaySection extends SettingsSection { constructor (parentDiv, settings) { - super (parentDiv, 'Model Display', settings); + super (parentDiv, t('Model Display'), settings); this.backgroundColorPicker = null; @@ -219,7 +221,7 @@ class SettingsModelDisplaySection extends SettingsSection let backgroundColorDiv = AddDiv (this.contentDiv, 'ov_sidebar_parameter'); let backgroundColorInput = AddDiv (backgroundColorDiv, 'ov_color_picker'); - AddDiv (backgroundColorDiv, null, 'Background Color'); + AddDiv (backgroundColorDiv, null, t('Background Color')); let predefinedBackgroundColors = ['#ffffffff', '#e3e3e3ff', '#c9c9c9ff', '#898989ff', '#5f5f5fff', '#494949ff', '#383838ff', '#0f0f0fff']; let defaultBackgroundColor = '#' + RGBAColorToHexString (this.settings.backgroundColor); this.backgroundColorPicker = AddColorPicker (backgroundColorInput, true, defaultBackgroundColor, predefinedBackgroundColors, (r, g, b, a) => { @@ -229,7 +231,7 @@ class SettingsModelDisplaySection extends SettingsSection this.environmentMapPhongDiv = AddDiv (this.contentDiv, 'ov_sidebar_parameter'); this.environmentMapPhongInput = AddDiv (this.environmentMapPhongDiv, 'ov_sidebar_image_picker'); - AddDiv (this.environmentMapPhongDiv, null, 'Background Image'); + AddDiv (this.environmentMapPhongDiv, null, t('Background Image')); this.environmentMapPhongInput.addEventListener ('click', () => { this.environmentMapPopup = new EnvironmentMapPopup (); this.environmentMapPopup.ShowPopup (this.environmentMapPhongInput, ShadingType.Phong, this.settings, { @@ -263,7 +265,7 @@ class SettingsModelDisplaySection extends SettingsSection let edgeParameterDiv = AddDiv (this.contentDiv, 'ov_sidebar_parameter'); this.edgeDisplayToggle = AddToggle (edgeParameterDiv, 'ov_sidebar_parameter_toggle'); - AddDiv (edgeParameterDiv, 'ov_sidebar_parameter_text', 'Show Edges'); + AddDiv (edgeParameterDiv, 'ov_sidebar_parameter_text', t('Show Edges')); this.edgeSettingsDiv = AddDiv (this.contentDiv, 'ov_sidebar_settings_padded'); this.edgeDisplayToggle.OnChange (() => { @@ -281,11 +283,11 @@ class SettingsModelDisplaySection extends SettingsSection this.settings.edgeSettings.edgeColor = new RGBColor (r, g, b); this.callbacks.onEdgeColorChange (); }); - AddDiv (edgeColorRow, null, 'Edge Color'); + AddDiv (edgeColorRow, null, t('Edge Color')); let thresholdRow = AddDiv (this.edgeSettingsDiv, 'ov_sidebar_settings_row large'); this.thresholdSlider = AddRangeSlider (thresholdRow, 0, 90); - this.thresholdSlider.setAttribute ('title', 'Edge Angle Threshold'); + this.thresholdSlider.setAttribute ('title', t('Edge Angle Threshold')); this.thresholdSliderValue = AddDomElement (thresholdRow, 'span', 'ov_slider_label'); this.thresholdSlider.addEventListener ('input', () => { this.thresholdSliderValue.innerHTML = this.thresholdSlider.value; @@ -375,7 +377,7 @@ class SettingsImportParametersSection extends SettingsSection { constructor (parentDiv, settings) { - super (parentDiv, 'Import Settings', settings); + super (parentDiv, t('Import Settings'), settings); this.defaultColorPickerDiv = null; this.defaultLineColorPickerDiv = null; this.defaultColorPicker = null; @@ -396,12 +398,12 @@ class SettingsImportParametersSection extends SettingsSection super.Init (callbacks); this.defaultColorPickerDiv = AddDiv (this.contentDiv); - this.defaultColorPicker = AddDefaultColorPicker (this.defaultColorPickerDiv, 'Default Color', this.settings.defaultColor, (r, g, b, a) => { + this.defaultColorPicker = AddDefaultColorPicker (this.defaultColorPickerDiv, t('Default Color'), this.settings.defaultColor, (r, g, b, a) => { this.settings.defaultColor = new RGBColor (r, g, b); this.callbacks.onDefaultColorChanged (); }); this.defaultLineColorPickerDiv = AddDiv (this.contentDiv); - this.defaultLineColorPicker = AddDefaultColorPicker (this.defaultLineColorPickerDiv, 'Default Line Color', this.settings.defaultLineColor, (r, g, b, a) => { + this.defaultLineColorPicker = AddDefaultColorPicker (this.defaultLineColorPickerDiv, t('Default Line Color'), this.settings.defaultLineColor, (r, g, b, a) => { this.settings.defaultLineColor = new RGBColor (r, g, b); this.callbacks.onDefaultColorChanged (); }); @@ -457,7 +459,7 @@ export class SidebarSettingsPanel extends SidebarPanel this.modelDisplaySection = new SettingsModelDisplaySection (this.sectionsDiv, this.settings); this.importParametersSection = new SettingsImportParametersSection (this.sectionsDiv, this.settings); - this.resetToDefaultsButton = AddDiv (this.contentDiv, 'ov_button ov_panel_button outline', 'Reset to Default'); + this.resetToDefaultsButton = AddDiv (this.contentDiv, 'ov_button ov_panel_button outline', t('Reset to Default')); this.resetToDefaultsButton.addEventListener ('click', () => { this.ResetToDefaults (); }); @@ -465,7 +467,7 @@ export class SidebarSettingsPanel extends SidebarPanel GetName () { - return 'Settings'; + return t('Settings'); } HasTitle () diff --git a/source/website/snapshotdialog.js b/source/website/snapshotdialog.js index 26dd97c0..660a4d27 100644 --- a/source/website/snapshotdialog.js +++ b/source/website/snapshotdialog.js @@ -5,6 +5,8 @@ import { DownloadUrlAsFile } from './utils.js'; import { CookieGetBoolVal, CookieGetIntVal, CookieGetStringVal, CookieSetBoolVal, CookieSetIntVal, CookieSetStringVal } from './cookiehandler.js'; import { HandleEvent } from './eventhandler.js'; +import { t } from './i18next.js'; + export function ShowSnapshotDialog (viewer) { function AddSizeRadioButton (parentDiv, id, text, isSelected, onChange) @@ -66,19 +68,19 @@ export function ShowSnapshotDialog (viewer) let customIndex = 3; let sizes = [ { - name : 'Small (1280x720)', + name : t('Small') + ' (1280x720)', size : [1280, 720] }, { - name : 'Medium (1920x1080)', + name : t('Medium') + ' (1920x1080)', size : [1920, 1080] }, { - name : 'Large (2560x1440)', + name : t('Large') + ' (2560x1440)', size : [2560, 1440] }, { - name : 'Custom', + name : t('Custom'), size : null, widthInput : null, heightInput : null @@ -86,16 +88,16 @@ export function ShowSnapshotDialog (viewer) ]; let dialog = new ButtonDialog (); - let contentDiv = dialog.Init ('Create Snapshot', [ + let contentDiv = dialog.Init (t('Create Snapshot'), [ { - name : 'Cancel', + name : t('Cancel'), subClass : 'outline', onClick () { dialog.Close (); } }, { - name : 'Create', + name : t('Create'), onClick () { dialog.Close (); HandleEvent ('snapshot_created', sizes[selectedIndex].name); @@ -135,11 +137,11 @@ export function ShowSnapshotDialog (viewer) }); } - customSize.widthInput = AddWidthHeightNumberInput (optionsDiv, 'Width', (val) => { + customSize.widthInput = AddWidthHeightNumberInput (optionsDiv, t('Width'), (val) => { UpdatePreview (viewer, previewImage, GetSize (sizes, selectedIndex), isTransparent); CookieSetIntVal ('ov_snapshot_custom_width', val); }); - customSize.heightInput = AddWidthHeightNumberInput (optionsDiv, 'Height', (val) => { + customSize.heightInput = AddWidthHeightNumberInput (optionsDiv, t('Height'), (val) => { UpdatePreview (viewer, previewImage, GetSize (sizes, selectedIndex), isTransparent); CookieSetIntVal ('ov_snapshot_custom_height', val); }); @@ -149,7 +151,7 @@ export function ShowSnapshotDialog (viewer) AddDomElement (optionsDiv, 'div', 'ov_snapshot_dialog_separator', null); - let transparentCheckbox = AddCheckbox (optionsDiv, 'snapshot_transparent_background', 'Transparent background', isTransparent, () => { + let transparentCheckbox = AddCheckbox (optionsDiv, 'snapshot_transparent_background', t('Transparent background'), isTransparent, () => { isTransparent = transparentCheckbox.checked; UpdatePreview (viewer, previewImage, GetSize (sizes, selectedIndex), isTransparent); CookieSetBoolVal ('ov_last_snapshot_transparent', isTransparent); diff --git a/source/website/threemodelloaderui.js b/source/website/threemodelloaderui.js index 8e32afb0..f5a198bd 100644 --- a/source/website/threemodelloaderui.js +++ b/source/website/threemodelloaderui.js @@ -5,6 +5,8 @@ import { ButtonDialog, ProgressDialog } from './dialog.js'; import { AddSvgIconElement } from './utils.js'; import { ImportErrorCode } from '../engine/import/importer.js'; +import { t } from './i18next.js'; + export class ThreeModelLoaderUI { constructor () @@ -40,10 +42,10 @@ export class ThreeModelLoaderUI }); }, onImportStart : () => { - progressDialog.SetText ('Importing Model'); + progressDialog.SetText (t('Importing Model')); }, onVisualizationStart : () => { - progressDialog.SetText ('Visualizing Model'); + progressDialog.SetText (t('Visualizing Model')); }, onModelFinished : (importResult, threeObject) => { progressDialog.Close (); @@ -74,26 +76,26 @@ export class ThreeModelLoaderUI { if (importError.code === ImportErrorCode.NoImportableFile) { return ShowMessageDialog ( - 'Something went wrong', - 'No importable file found.', + t('Something went wrong'), + t('No importable file found.'), null ); } else if (importError.code === ImportErrorCode.FailedToLoadFile) { return ShowMessageDialog ( - 'Something went wrong', - 'Failed to load file for import.', - 'The remote server refused to fulfill the request. Check if the url is correct, and make sure that CORS requests are allowed on the remote server.' + t('Something went wrong'), + t('Failed to load file for import.'), + t('The remote server refused to fulfill the request. Check if the url is correct, and make sure that CORS requests are allowed on the remote server.') ); } else if (importError.code === ImportErrorCode.ImportFailed) { return ShowMessageDialog ( - 'Something went wrong', - 'Failed to import model.', + t('Something went wrong'), + t( 'Failed to import model.'), importError.message ); } else { return ShowMessageDialog ( - 'Something went wrong', - 'Unknown error.', + t('Something went wrong'), + t('Unknown error.'), null ); } diff --git a/source/website/utils.js b/source/website/utils.js index a51592f8..12ba5cdb 100644 --- a/source/website/utils.js +++ b/source/website/utils.js @@ -2,6 +2,8 @@ import { RGBColor, RGBColorToHexString } from '../engine/model/color.js'; import { CreateObjectUrl } from '../engine/io/bufferutils.js'; import { AddDiv, CreateDiv, AddDomElement } from '../engine/viewer/domutils.js'; +import { t } from './i18next.js'; + export function GetNameOrDefault (originalName, defaultName) { if (originalName.length > 0) { @@ -12,18 +14,18 @@ export function GetNameOrDefault (originalName, defaultName) export function GetNodeName (originalName) { - return GetNameOrDefault (originalName, 'No Name'); + return GetNameOrDefault (originalName, t('No Name')); } export function GetMeshName (originalNodeName, originalMeshName) { let originalName = (originalNodeName.length > 0 ? originalNodeName : originalMeshName); - return GetNameOrDefault (originalName, 'No Name'); + return GetNameOrDefault (originalName, t('No Name')); } export function GetMaterialName (originalName) { - return GetNameOrDefault (originalName, 'No Name'); + return GetNameOrDefault (originalName, t('No Name')); } export function IsHoverEnabled () diff --git a/source/website/website.js b/source/website/website.js index c75450c4..bd18f720 100644 --- a/source/website/website.js +++ b/source/website/website.js @@ -28,6 +28,7 @@ import { CreateVerticalSplitter } from './splitter.js'; import { EnumeratePlugins, PluginType } from './pluginregistry.js'; import { EnvironmentSettings } from '../engine/viewer/shadingmodel.js'; import { IntersectionMode } from '../engine/viewer/viewermodel.js'; +import { t } from './i18next.js'; const WebsiteUIState = { @@ -338,7 +339,7 @@ export class Website let items = []; if (meshUserData === null) { items.push ({ - name : 'Fit model to window', + name : t('Fit model to window'), icon : 'fit', onClick : () => { this.FitModelToWindow (false); @@ -346,7 +347,7 @@ export class Website }); if (this.navigator.HasHiddenMesh ()) { items.push ({ - name : 'Show all meshes', + name : t('Show all meshes'), icon : 'visible', onClick : () => { this.navigator.ShowAllMeshes (true); @@ -355,14 +356,14 @@ export class Website } } else { items.push ({ - name : 'Hide mesh', + name : t('Hide mesh'), icon : 'hidden', onClick : () => { this.navigator.ToggleMeshVisibility (meshUserData.originalMeshInstance.id); } }); items.push ({ - name : 'Fit mesh to window', + name : t('Fit mesh to window'), icon : 'fit', onClick : () => { this.navigator.FitMeshToWindow (meshUserData.originalMeshInstance.id); @@ -371,7 +372,7 @@ export class Website if (this.navigator.MeshItemCount () > 1) { let isMeshIsolated = this.navigator.IsMeshIsolated (meshUserData.originalMeshInstance.id); items.push ({ - name : isMeshIsolated ? 'Remove isolation' : 'Isolate mesh', + name : t(isMeshIsolated ? 'Remove isolation' : 'Isolate mesh'), icon : isMeshIsolated ? 'deisolate' : 'isolate', onClick : () => { if (isMeshIsolated) { @@ -660,10 +661,10 @@ export class Website let navigationModeIndex = (this.cameraSettings.navigationMode === NavigationMode.FixedUpVector ? 0 : 1); let projectionModeIndex = (this.cameraSettings.projectionMode === ProjectionMode.Perspective ? 0 : 1); - AddButton (this.toolbar, 'open', 'Open from your device', [], () => { + AddButton (this.toolbar, 'open', t('Open from your device'), [], () => { this.OpenFileBrowserDialog (); }); - AddButton (this.toolbar, 'open_url', 'Open from url', [], () => { + AddButton (this.toolbar, 'open_url', t('Open from url'), [], () => { ShowOpenUrlDialog ((urls) => { if (urls.length > 0) { this.hashHandler.SetModelFilesToHash (urls); @@ -671,20 +672,20 @@ export class Website }); }); AddSeparator (this.toolbar, ['only_on_model']); - AddButton (this.toolbar, 'fit', 'Fit model to window', ['only_on_model'], () => { + AddButton (this.toolbar, 'fit', t('Fit model to window'), ['only_on_model'], () => { this.FitModelToWindow (false); }); - AddButton (this.toolbar, 'up_y', 'Set Y axis as up vector', ['only_on_model'], () => { + AddButton (this.toolbar, 'up_y', t('Set Y axis as up vector'), ['only_on_model'], () => { this.viewer.SetUpVector (Direction.Y, true); }); - AddButton (this.toolbar, 'up_z', 'Set Z axis as up vector', ['only_on_model'], () => { + AddButton (this.toolbar, 'up_z', t('Set Z axis as up vector'), ['only_on_model'], () => { this.viewer.SetUpVector (Direction.Z, true); }); - AddButton (this.toolbar, 'flip', 'Flip up vector', ['only_on_model'], () => { + AddButton (this.toolbar, 'flip', t('Flip up vector'), ['only_on_model'], () => { this.viewer.FlipUpVector (); }); AddSeparator (this.toolbar, ['only_full_width', 'only_on_model']); - AddRadioButton (this.toolbar, ['fix_up_on', 'fix_up_off'], ['Fixed up vector', 'Free orbit'], navigationModeIndex, ['only_full_width', 'only_on_model'], (buttonIndex) => { + AddRadioButton (this.toolbar, ['fix_up_on', 'fix_up_off'], [t('Fixed up vector'), t('Free orbit')], navigationModeIndex, ['only_full_width', 'only_on_model'], (buttonIndex) => { if (buttonIndex === 0) { this.cameraSettings.navigationMode = NavigationMode.FixedUpVector; } else if (buttonIndex === 1) { @@ -694,7 +695,7 @@ export class Website this.viewer.SetNavigationMode (this.cameraSettings.navigationMode); }); AddSeparator (this.toolbar, ['only_full_width', 'only_on_model']); - AddRadioButton (this.toolbar, ['camera_perspective', 'camera_orthographic'], ['Perspective camera', 'Orthographic camera'], projectionModeIndex, ['only_full_width', 'only_on_model'], (buttonIndex) => { + AddRadioButton (this.toolbar, ['camera_perspective', 'camera_orthographic'], [t('Perspective camera'), t('Orthographic camera')], projectionModeIndex, ['only_full_width', 'only_on_model'], (buttonIndex) => { if (buttonIndex === 0) { this.cameraSettings.projectionMode = ProjectionMode.Perspective; } else if (buttonIndex === 1) { @@ -705,30 +706,30 @@ export class Website this.sidebar.UpdateControlsVisibility (); }); AddSeparator (this.toolbar, ['only_full_width', 'only_on_model']); - let measureToolButton = AddPushButton (this.toolbar, 'measure', 'Measure', ['only_full_width', 'only_on_model'], (isSelected) => { - HandleEvent ('measure_tool_activated', isSelected ? 'on' : 'off'); + let measureToolButton = AddPushButton (this.toolbar, 'measure', t('Measure'), ['only_full_width', 'only_on_model'], (isSelected) => { + HandleEvent ('measure_tool_activated', isSelected ? t('on') : t('off')); this.navigator.SetSelection (null); this.measureTool.SetActive (isSelected); }); this.measureTool.SetButton (measureToolButton); AddSeparator (this.toolbar, ['only_full_width', 'only_on_model']); - AddButton (this.toolbar, 'download', 'Download', ['only_full_width', 'only_on_model'], () => { + AddButton (this.toolbar, 'download', t('Download'), ['only_full_width', 'only_on_model'], () => { HandleEvent ('model_downloaded', ''); let importer = this.modelLoaderUI.GetImporter (); DownloadModel (importer); }); - AddButton (this.toolbar, 'export', 'Export', ['only_full_width', 'only_on_model'], () => { + AddButton (this.toolbar, 'export', t('Export'), ['only_full_width', 'only_on_model'], () => { ShowExportDialog (this.model, this.viewer, { isMeshVisible : (meshInstanceId) => { return this.navigator.IsMeshVisible (meshInstanceId); } }); }); - AddButton (this.toolbar, 'share', 'Share', ['only_full_width', 'only_on_model'], () => { + AddButton (this.toolbar, 'share', t('Share'), ['only_full_width', 'only_on_model'], () => { ShowSharingDialog (importer.GetFileList (), this.settings, this.viewer); }); AddSeparator (this.toolbar, ['only_full_width', 'only_on_model']); - AddButton (this.toolbar, 'snapshot', 'Create snapshot', ['only_full_width', 'only_on_model'], () => { + AddButton (this.toolbar, 'snapshot', t('Create snapshot'), ['only_full_width', 'only_on_model'], () => { ShowSnapshotDialog (this.viewer); }); @@ -747,7 +748,7 @@ export class Website }); let selectedTheme = (this.settings.themeId === Theme.Light ? 1 : 0); - AddRadioButton (this.toolbar, ['dark_mode', 'light_mode'], ['Dark mode', 'Light mode'], selectedTheme, ['align_right'], (buttonIndex) => { + AddRadioButton (this.toolbar, ['dark_mode', 'light_mode'], [t('Dark mode'), t('Light mode')], selectedTheme, ['align_right'], (buttonIndex) => { if (buttonIndex === 0) { this.settings.themeId = Theme.Dark; } else if (buttonIndex === 1) { @@ -967,10 +968,11 @@ export class Website return; } - let text = 'This website uses cookies to offer you better user experience. See the details at the Cookies Policy page.'; + let link = t('{{text}}', { text: t('Cookies Policy') }); + let text = t('This website uses cookies to offer you better user experience. See the details at the {{- link }} page.', { link: link} ); let popupDiv = AddDiv (document.body, 'ov_bottom_floating_panel'); AddDiv (popupDiv, 'ov_floating_panel_text', text); - let acceptButton = AddDiv (popupDiv, 'ov_button ov_floating_panel_button', 'Accept'); + let acceptButton = AddDiv (popupDiv, 'ov_button ov_floating_panel_button', t('Accept')); acceptButton.addEventListener ('click', () => { CookieSetBoolVal ('ov_cookie_consent', true); popupDiv.remove (); diff --git a/website/index.html b/website/index.html index dcfa68e2..618a8ad7 100644 --- a/website/index.html +++ b/website/index.html @@ -68,10 +68,10 @@
-
Check an example file:
+
Check an example file:
3dm 3ds From 39920fe6652bb641f0710e8d9a374a683620e4c7 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 8 Apr 2024 22:24:13 +0800 Subject: [PATCH 2/5] fix: test --- package-lock.json | 87 +++++++++++++++++++++++++++++++++++++++ package.json | 1 + source/website/i18next.js | 29 +++++++------ tools/rollup.js | 5 ++- 4 files changed, 109 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8384d5b8..28570fb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "web-ifc": "0.0.44" }, "devDependencies": { + "@rollup/plugin-json": "6.1.0", "@types/node": "^20.1.0", "esbuild": "^0.19.0", "eslint": "^8.29.0", @@ -1277,6 +1278,48 @@ "node": ">= 10" } }, + "node_modules/@rollup/plugin-json": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.1.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.5.0.tgz", @@ -1466,6 +1509,12 @@ "node": ">=10.13.0" } }, + "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 + }, "node_modules/@types/linkify-it": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", @@ -2767,6 +2816,12 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -6834,6 +6889,26 @@ "dev": true, "optional": true }, + "@rollup/plugin-json": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.1.0" + } + }, + "@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + } + }, "@rollup/rollup-android-arm-eabi": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.5.0.tgz", @@ -6945,6 +7020,12 @@ "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "dev": true }, + "@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 + }, "@types/linkify-it": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", @@ -7946,6 +8027,12 @@ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", diff --git a/package.json b/package.json index 01f5c473..4efbd601 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "update_engine_exports": "run-python3 tools/update_engine_exports.py" }, "devDependencies": { + "@rollup/plugin-json": "6.1.0", "@types/node": "^20.1.0", "esbuild": "^0.19.0", "eslint": "^8.29.0", diff --git a/source/website/i18next.js b/source/website/i18next.js index aff18b9d..07dd2d5e 100644 --- a/source/website/i18next.js +++ b/source/website/i18next.js @@ -1,16 +1,19 @@ -import i18next from 'i18next'; -import { CookieGetStringVal } from './cookiehandler.js'; +import i18next from "i18next"; +import { CookieGetStringVal } from "./cookiehandler.js"; -import zhCN from './locale/zh-CN.json'; +import zhCN from "./locale/zh-CN.json" assert { type: "json" }; -const defaultLang = CookieGetStringVal('ov_language', navigator.language); +const defaultLang = + typeof navigator !== "undefined" + ? CookieGetStringVal("ov_language", navigator.language) + : ""; i18next.init({ lng: defaultLang, // if you're u sing a language detector, do not define the lng option debug: false, - supportedLngs: ['zh-CN'], + supportedLngs: ["zh-CN"], resources: { - 'zh-CN': { translation: zhCN }, + "zh-CN": { translation: zhCN }, }, }); @@ -18,10 +21,12 @@ const t = i18next.t; export { i18next, t }; -// translate HTML -document.addEventListener('DOMContentLoaded', () => { - document.querySelectorAll('[data-i18n]').forEach((ele) => { - const translateKey = ele.getAttribute('data-i18n') || ele.textContent; - ele.textContent = t(translateKey); +if (typeof document !== "undefined") { + // translate HTML + document.addEventListener("DOMContentLoaded", () => { + document.querySelectorAll("[data-i18n]").forEach((ele) => { + const translateKey = ele.getAttribute("data-i18n") || ele.textContent; + ele.textContent = t(translateKey); + }); }); -}); +} diff --git a/tools/rollup.js b/tools/rollup.js index 4ebb8358..fa19fe59 100644 --- a/tools/rollup.js +++ b/tools/rollup.js @@ -1,3 +1,5 @@ +import json from '@rollup/plugin-json'; + export default [ { input: 'source/engine/main.js', @@ -15,6 +17,7 @@ export default [ 'three/examples/jsm/loaders/VRMLLoader.js', 'three/examples/jsm/loaders/3MFLoader.js', 'three/examples/jsm/loaders/AMFLoader.js' - ] + ], + plugins: [json()] } ]; From 8f1f1cd823961e5d286a371906272aef368d1a3c Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 8 Apr 2024 22:31:54 +0800 Subject: [PATCH 3/5] fix: eslint --- package-lock.json | 1315 ++++++++++++++++++++++++++++++++++++- package.json | 13 +- source/website/i18next.js | 24 +- 3 files changed, 1325 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 28570fb9..cf774100 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,8 @@ "web-ifc": "0.0.44" }, "devDependencies": { + "@babel/eslint-parser": "7.24.1", + "@babel/plugin-syntax-import-assertions": "7.24.1", "@rollup/plugin-json": "6.1.0", "@types/node": "^20.1.0", "esbuild": "^0.19.0", @@ -32,7 +34,7 @@ "rollup": "^4.0.2", "run-python3": "^0.0.5", "svgo": "^3.0.2", - "typescript": "^5.0.4" + "typescript": "5.4.4" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -44,16 +46,435 @@ "node": ">=0.10.0" } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@assemblyscript/loader": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", "dev": true }, + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "dev": true, + "peer": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.4", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz", + "integrity": "sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==", + "dev": true, + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "peer": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "peer": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "peer": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.4.tgz", - "integrity": "sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -62,6 +483,21 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", + "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/runtime": { "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.4.tgz", @@ -78,6 +514,68 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.19.6", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.6.tgz", @@ -989,6 +1487,59 @@ "regenerator-runtime": "^0.13.3" } }, + "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, + "peer": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "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, + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "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, + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true, + "peer": true + }, + "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, + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jsdoc/salty": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.6.tgz", @@ -1001,6 +1552,37 @@ "node": ">=v12.0.0" } }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { + "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" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { + "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" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1829,6 +2411,39 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -1988,6 +2603,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001607", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001607.tgz", + "integrity": "sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true + }, "node_modules/capital-case": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", @@ -2208,6 +2844,13 @@ "upper-case": "^2.0.2" } }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "peer": true + }, "node_modules/core-js": { "version": "3.32.2", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.2.tgz", @@ -2507,6 +3150,13 @@ "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.6.tgz", "integrity": "sha512-+3NaRjWktb5r61ZFoDejlykPEFKT5N/LkbXsaddlw6xNSXBanUYpFc2AXXpbJDilPHazcSreU/DpQIaxfX0NfQ==" }, + "node_modules/electron-to-chromium": { + "version": "1.4.729", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.729.tgz", + "integrity": "sha512-bx7+5Saea/qu14kmPTDHQxkp2UnziG3iajUQu3BxFvCOnpAJdDbMV4rSl+EqFDkkpNNVUFlR1kDfpL59xfy1HA==", + "dev": true, + "peer": true + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3131,6 +3781,16 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/geometry-interfaces": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/geometry-interfaces/-/geometry-interfaces-1.1.4.tgz", @@ -3737,6 +4397,13 @@ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", "dev": true }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "peer": true + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3796,6 +4463,19 @@ "node": ">=8" } }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "peer": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3814,6 +4494,19 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "peer": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -4453,6 +5146,13 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true, + "peer": true + }, "node_modules/nopt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", @@ -5613,6 +6313,16 @@ "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", "dev": true }, + "node_modules/to-fast-properties": { + "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, + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5733,9 +6443,9 @@ } }, "node_modules/typescript": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", - "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", + "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -5812,6 +6522,37 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/upper-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", @@ -6119,18 +6860,356 @@ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true }, + "@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "peer": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "@assemblyscript/loader": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", "dev": true }, + "@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + } + }, + "@babel/compat-data": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "dev": true, + "peer": true + }, + "@babel/core": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "dev": true, + "peer": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.4", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "peer": true + } + } + }, + "@babel/eslint-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz", + "integrity": "sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==", + "dev": true, + "requires": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", + "dev": true, + "peer": true, + "requires": { + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "peer": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "peer": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "peer": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "peer": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "peer": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "peer": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, + "peer": true, + "requires": { + "@babel/types": "^7.24.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "peer": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "peer": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true, + "peer": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "peer": true + }, + "@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "peer": true + }, + "@babel/helpers": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", + "dev": true, + "peer": true, + "requires": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" + } + }, + "@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "peer": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "peer": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "@babel/parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.4.tgz", - "integrity": "sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "dev": true }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", + "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.0" + } + }, "@babel/runtime": { "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.4.tgz", @@ -6146,6 +7225,58 @@ } } }, + "@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "peer": true, + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + } + }, + "@babel/traverse": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "peer": true + } + } + }, + "@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, "@esbuild/android-arm": { "version": "0.19.6", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.6.tgz", @@ -6730,6 +7861,50 @@ "regenerator-runtime": "^0.13.3" } }, + "@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, + "peer": true, + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/resolve-uri": { + "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, + "peer": true + }, + "@jridgewell/set-array": { + "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, + "peer": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true, + "peer": true + }, + "@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, + "peer": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "@jsdoc/salty": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.6.tgz", @@ -6739,6 +7914,33 @@ "lodash": "^4.17.21" } }, + "@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "requires": { + "eslint-scope": "5.1.1" + }, + "dependencies": { + "eslint-scope": { + "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, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -7275,6 +8477,19 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "peer": true, + "requires": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, "buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -7392,6 +8607,13 @@ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, + "caniuse-lite": { + "version": "1.0.30001607", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001607.tgz", + "integrity": "sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==", + "dev": true, + "peer": true + }, "capital-case": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", @@ -7570,6 +8792,13 @@ "upper-case": "^2.0.2" } }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "peer": true + }, "core-js": { "version": "3.32.2", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.2.tgz", @@ -7795,6 +9024,13 @@ "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.6.tgz", "integrity": "sha512-+3NaRjWktb5r61ZFoDejlykPEFKT5N/LkbXsaddlw6xNSXBanUYpFc2AXXpbJDilPHazcSreU/DpQIaxfX0NfQ==" }, + "electron-to-chromium": { + "version": "1.4.729", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.729.tgz", + "integrity": "sha512-bx7+5Saea/qu14kmPTDHQxkp2UnziG3iajUQu3BxFvCOnpAJdDbMV4rSl+EqFDkkpNNVUFlR1kDfpL59xfy1HA==", + "dev": true, + "peer": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -8277,6 +9513,13 @@ "wide-align": "^1.1.5" } }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "peer": true + }, "geometry-interfaces": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/geometry-interfaces/-/geometry-interfaces-1.1.4.tgz", @@ -8738,6 +9981,13 @@ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", "dev": true }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "peer": true + }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -8787,6 +10037,13 @@ } } }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "peer": true + }, "json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -8805,6 +10062,13 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "peer": true + }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -9317,6 +10581,13 @@ "dev": true, "optional": true }, + "node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true, + "peer": true + }, "nopt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", @@ -10195,6 +11466,13 @@ "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", "dev": true }, + "to-fast-properties": { + "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, + "peer": true + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -10285,9 +11563,9 @@ "dev": true }, "typescript": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", - "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", + "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", "dev": true }, "uc.micro": { @@ -10342,6 +11620,17 @@ "imurmurhash": "^0.1.4" } }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "peer": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "upper-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", diff --git a/package.json b/package.json index 4efbd601..262e4de1 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,8 @@ "update_engine_exports": "run-python3 tools/update_engine_exports.py" }, "devDependencies": { + "@babel/eslint-parser": "7.24.1", + "@babel/plugin-syntax-import-assertions": "7.24.1", "@rollup/plugin-json": "6.1.0", "@types/node": "^20.1.0", "esbuild": "^0.19.0", @@ -71,7 +73,7 @@ "rollup": "^4.0.2", "run-python3": "^0.0.5", "svgo": "^3.0.2", - "typescript": "^5.0.4" + "typescript": "5.4.4" }, "dependencies": { "@simonwep/pickr": "1.9.0", @@ -100,9 +102,16 @@ "WebIFC": "readonly", "occtimportjs": "readonly" }, + "parser": "@babel/eslint-parser", "parserOptions": { "ecmaVersion": 12, - "sourceType": "module" + "sourceType": "module", + "requireConfigFile": false, + "babelOptions": { + "plugins": [ + "@babel/plugin-syntax-import-assertions" + ] + } }, "plugins": [ "unused-imports" diff --git a/source/website/i18next.js b/source/website/i18next.js index 07dd2d5e..dcd1dc2e 100644 --- a/source/website/i18next.js +++ b/source/website/i18next.js @@ -1,19 +1,19 @@ -import i18next from "i18next"; -import { CookieGetStringVal } from "./cookiehandler.js"; +import i18next from 'i18next'; +import { CookieGetStringVal } from './cookiehandler.js'; -import zhCN from "./locale/zh-CN.json" assert { type: "json" }; +import zhCN from './locale/zh-CN.json' assert { type: 'json' }; const defaultLang = - typeof navigator !== "undefined" - ? CookieGetStringVal("ov_language", navigator.language) - : ""; + typeof navigator !== 'undefined' + ? CookieGetStringVal('ov_language', navigator.language) + : ''; i18next.init({ lng: defaultLang, // if you're u sing a language detector, do not define the lng option debug: false, - supportedLngs: ["zh-CN"], + supportedLngs: ['zh-CN'], resources: { - "zh-CN": { translation: zhCN }, + 'zh-CN': { translation: zhCN }, }, }); @@ -21,11 +21,11 @@ const t = i18next.t; export { i18next, t }; -if (typeof document !== "undefined") { +if (typeof document !== 'undefined') { // translate HTML - document.addEventListener("DOMContentLoaded", () => { - document.querySelectorAll("[data-i18n]").forEach((ele) => { - const translateKey = ele.getAttribute("data-i18n") || ele.textContent; + document.addEventListener('DOMContentLoaded', () => { + document.querySelectorAll('[data-i18n]').forEach((ele) => { + const translateKey = ele.getAttribute('data-i18n') || ele.textContent; ele.textContent = t(translateKey); }); }); From 7e7053e718f53485102b15081aec9fbb689bb095 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 8 Apr 2024 22:43:12 +0800 Subject: [PATCH 4/5] feat: support specify the locale from hash URL params --- source/engine/parameters/parameterlist.js | 6 ++++++ source/website/hashhandler.js | 6 ++++++ source/website/i18next.js | 7 +++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/source/engine/parameters/parameterlist.js b/source/engine/parameters/parameterlist.js index d1d171f8..354ff9ed 100644 --- a/source/engine/parameters/parameterlist.js +++ b/source/engine/parameters/parameterlist.js @@ -362,6 +362,12 @@ export class ParameterListParser return ParameterConverter.StringToEdgeSettings (edgeSettingsParams); } + GetLocale () + { + let localeParams = this.GetKeywordParams ('locale'); + return localeParams; + } + GetKeywordParams (keyword) { if (this.paramList === null || this.paramList.length === 0) { diff --git a/source/website/hashhandler.js b/source/website/hashhandler.js index b57b2575..c642eea4 100644 --- a/source/website/hashhandler.js +++ b/source/website/hashhandler.js @@ -84,6 +84,12 @@ export class HashHandler return parser.GetEdgeSettings (); } + GetLocaleFromHash () + { + let parser = CreateUrlParser (this.GetHash ()); + return parser.GetLocale (); + } + GetHash () { return window.location.hash.substring (1); diff --git a/source/website/i18next.js b/source/website/i18next.js index dcd1dc2e..468fa52e 100644 --- a/source/website/i18next.js +++ b/source/website/i18next.js @@ -1,11 +1,14 @@ import i18next from 'i18next'; import { CookieGetStringVal } from './cookiehandler.js'; - +import { HashHandler } from './hashhandler.js'; import zhCN from './locale/zh-CN.json' assert { type: 'json' }; +const hashHandler = new HashHandler(); + const defaultLang = typeof navigator !== 'undefined' - ? CookieGetStringVal('ov_language', navigator.language) + ? hashHandler.GetLocaleFromHash() || + CookieGetStringVal('ov_language', navigator.language) : ''; i18next.init({ From 52126ff152a223b28f751d3906b4141ef8c5bc46 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 9 Apr 2024 09:30:47 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=94=99=E8=AF=AF=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/website/exportdialog.js | 2 +- source/website/locale/zh-CN.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/source/website/exportdialog.js b/source/website/exportdialog.js index f90d5efe..f2e79aae 100644 --- a/source/website/exportdialog.js +++ b/source/website/exportdialog.js @@ -80,7 +80,7 @@ class ModelExporterUI if (exporterModel.MeshInstanceCount () === 0) { ShowMessageDialog ( t('Export Failed'), - t('The model doesn\'t contain any meshes.'), + 'The model doesn\'t contain any meshes.', null ); return; diff --git a/source/website/locale/zh-CN.json b/source/website/locale/zh-CN.json index c9bf122d..00d54daa 100644 --- a/source/website/locale/zh-CN.json +++ b/source/website/locale/zh-CN.json @@ -72,7 +72,6 @@ "Copied": "已复制", "Select the format from the list below, and adjust the settings of the selected format.": "从下面的列表中选择格式,并调整所选格式的设置。", "Export Failed": "导出失败", - "The model doesn\\'t contain any meshes.": "模型不包含任何网格。", "Exporting Model": "模型导出中", "Scope": "范围", "Rotation": "旋转",