diff --git a/source/website/dialogs.js b/source/website/dialogs.js
index 602de83c..a5ea97ec 100644
--- a/source/website/dialogs.js
+++ b/source/website/dialogs.js
@@ -1,12 +1,13 @@
import { AddDiv } from '../engine/viewer/domutils.js';
import { ButtonDialog, ListPopup } from './dialog.js';
+import { Loc } from '../engine/core/localization.js';
export function ShowMessageDialog (title, message, subMessage)
{
let dialog = new ButtonDialog ();
let contentDiv = dialog.Init (title, [
{
- name : 'OK',
+ name : Loc ('OK'),
onClick () {
dialog.Close ();
}
diff --git a/source/website/exportdialog.js b/source/website/exportdialog.js
index 65cd15d3..988a6bcf 100644
--- a/source/website/exportdialog.js
+++ b/source/website/exportdialog.js
@@ -11,6 +11,7 @@ import { ShowMessageDialog } from './dialogs.js';
import { DownloadArrayBufferAsFile } from './utils.js';
import { CookieGetStringVal, CookieSetStringVal } from './cookiehandler.js';
import { HandleEvent } from './eventhandler.js';
+import { Loc } from '../engine/core/localization.js';
import * as fflate from 'fflate';
@@ -53,8 +54,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, Loc ('Scope'), 'ov_last_scope', [Loc ('Entire Model'), Loc ('Visible Only')], 1);
+ this.rotationSelect = AddSelectItem (parametersDiv, Loc ('Rotation'), 'ov_last_rotation', [Loc ('No Rotation'), Loc ('-90 Degrees'), Loc ('90 Degrees')], 0);
}
ExportModel (model, callbacks)
@@ -77,15 +78,15 @@ class ModelExporterUI
let exporterModel = new ExporterModel (model, settings);
if (exporterModel.MeshInstanceCount () === 0) {
ShowMessageDialog (
- 'Export Failed',
- 'The model doesn\'t contain any meshes.',
+ Loc ('Export Failed'),
+ Loc ('The model doesn\'t contain any meshes.'),
null
);
return;
}
let progressDialog = new ProgressDialog ();
- progressDialog.Init ('Exporting Model');
+ progressDialog.Init (Loc ('Exporting Model'));
progressDialog.Open ();
RunTaskAsync (() => {
@@ -142,16 +143,16 @@ class ExportDialog
Open (model, viewer)
{
let mainDialog = new ButtonDialog ();
- let contentDiv = mainDialog.Init ('Export', [
+ let contentDiv = mainDialog.Init (Loc ('Export'), [
{
- name : 'Close',
+ name : Loc ('Close'),
subClass : 'outline',
onClick () {
mainDialog.Close ();
}
},
{
- name : 'Export',
+ name : Loc ('Export'),
onClick : () => {
mainDialog.Close ();
this.ExportFormat (model, viewer);
@@ -159,7 +160,7 @@ class ExportDialog
}
]);
- let text = 'Select the format from the list below, and adjust the settings of the selected format.';
+ let text = Loc ('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/measuretool.js b/source/website/measuretool.js
index 73426084..c3a79f48 100644
--- a/source/website/measuretool.js
+++ b/source/website/measuretool.js
@@ -1,6 +1,7 @@
import { BigEps, IsEqualEps, RadDeg } from '../engine/geometry/geometry.js';
import { AddDiv, ClearDomElement } from '../engine/viewer/domutils.js';
import { AddSvgIconElement, IsDarkTextNeededForColor } from './utils.js';
+import { Loc } from '../engine/core/localization.js';
import * as THREE from 'three';
import { ColorComponentToFloat, RGBColor } from '../engine/model/color.js';
@@ -231,9 +232,9 @@ export class MeasureTool
this.panel.style.backgroundColor = 'transparent';
}
if (this.markers.length === 0) {
- this.panel.innerHTML = 'Select a point.';
+ this.panel.innerHTML = Loc ('Select a point.');
} else if (this.markers.length === 1) {
- this.panel.innerHTML = 'Select another point.';
+ this.panel.innerHTML = Loc ('Select another point.');
} else {
let calcResult = CalculateMarkerValues (this.markers[0], this.markers[1]);
diff --git a/source/website/navigatorfilespanel.js b/source/website/navigatorfilespanel.js
index 4879c8e8..b77dc5de 100644
--- a/source/website/navigatorfilespanel.js
+++ b/source/website/navigatorfilespanel.js
@@ -1,6 +1,7 @@
import { SetDomElementHeight, GetDomElementOuterHeight } from '../engine/viewer/domutils.js';
import { NavigatorPanel } from './navigatorpanel.js';
import { TreeViewButton, TreeViewButtonItem, TreeViewGroupItem, TreeViewSingleItem } from './treeview.js';
+import { Loc } from '../engine/core/localization.js';
export class NavigatorFilesPanel extends NavigatorPanel
{
@@ -11,7 +12,7 @@ export class NavigatorFilesPanel extends NavigatorPanel
GetName ()
{
- return 'Files';
+ return Loc ('Files');
}
GetIcon ()
@@ -38,7 +39,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 (Loc ('Missing Files'), null);
missingFilesItem.ShowChildren (true);
this.treeView.AddChild (missingFilesItem);
for (let i = 0; i < missingFiles.length; i++) {
@@ -51,7 +52,7 @@ export class NavigatorFilesPanel extends NavigatorPanel
item.AppendButton (browseButton);
missingFilesItem.AddChild (item);
}
- let filesItem = new TreeViewGroupItem ('Available Files', null);
+ let filesItem = new TreeViewGroupItem (Loc ('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..8677e4ea 100644
--- a/source/website/navigatormaterialspanel.js
+++ b/source/website/navigatormaterialspanel.js
@@ -3,6 +3,7 @@ import { CalculatePopupPositionToElementBottomRight, ShowListPopup } from './dia
import { MaterialItem } from './navigatoritems.js';
import { NavigatorPanel, NavigatorPopupButton } from './navigatorpanel.js';
import { GetMaterialName, GetMeshName } from './utils.js';
+import { Loc, FLoc } from '../engine/core/localization.js';
class NavigatorMeshesPopupButton extends NavigatorPopupButton
{
@@ -19,7 +20,7 @@ class NavigatorMeshesPopupButton extends NavigatorPopupButton
return;
}
- let meshesText = 'Meshes (' + this.meshInstanceArray.length + ')';
+ let meshesText = FLoc ('Meshes ({0})', this.meshInstanceArray.length);
this.buttonText.innerHTML = meshesText;
}
@@ -74,7 +75,7 @@ export class NavigatorMaterialsPanel extends NavigatorPanel
GetName ()
{
- return 'Materials';
+ return Loc ('Materials');
}
GetIcon ()
diff --git a/source/website/navigatormeshespanel.js b/source/website/navigatormeshespanel.js
index 19303380..d9a9c25b 100644
--- a/source/website/navigatormeshespanel.js
+++ b/source/website/navigatormeshespanel.js
@@ -4,6 +4,7 @@ import { CalculatePopupPositionToElementBottomRight, ShowListPopup } from './dia
import { MeshItem, NavigatorItemRecurse, NodeItem } from './navigatoritems.js';
import { NavigatorPanel, NavigatorPopupButton } from './navigatorpanel.js';
import { AddSvgIconElement, GetMaterialName, GetMeshName, GetNodeName, SetSvgIconImageElement } from './utils.js';
+import { Loc, FLoc } from '../engine/core/localization.js';
const MeshesPanelMode =
{
@@ -27,7 +28,7 @@ class NavigatorMaterialsPopupButton extends NavigatorPopupButton
return;
}
- let materialsText = 'Materials (' + this.materialInfoArray.length + ')';
+ let materialsText = FLoc ('Materials ({0})', this.materialInfoArray.length);
this.buttonText.innerHTML = materialsText;
}
@@ -86,7 +87,7 @@ export class NavigatorMeshesPanel extends NavigatorPanel
GetName ()
{
- return 'Meshes';
+ return Loc ('Meshes');
}
GetIcon ()
@@ -228,38 +229,38 @@ export class NavigatorMeshesPanel extends NavigatorPanel
this.buttons = {
flatList : {
- name : 'Flat list',
+ name : Loc ('Flat list'),
icon : 'flat_list',
div : null,
iconDiv : null
},
treeView : {
- name : 'Tree view',
+ name : Loc ('Tree view'),
icon : 'tree_view',
div : null,
iconDiv : null
},
separator : null,
expandAll : {
- name : 'Expand all',
+ name : Loc ('Expand all'),
icon : 'expand',
div : null,
iconDiv : null
},
collapseAll : {
- name : 'Collapse all',
+ name : Loc ('Collapse all'),
icon : 'collapse',
div : null,
iconDiv : null
},
showHideMeshes : {
- name : 'Show/hide meshes',
+ name : Loc ('Show/hide meshes'),
icon : 'visible',
div : null,
iconDiv : null
},
fitToWindow : {
- name : 'Fit meshes to window',
+ name : Loc ('Fit meshes to window'),
icon : 'fit',
div : null,
iconDiv : null
diff --git a/source/website/openurldialog.js b/source/website/openurldialog.js
index ca5aa2c6..f934e706 100644
--- a/source/website/openurldialog.js
+++ b/source/website/openurldialog.js
@@ -1,21 +1,22 @@
import { ReadLines } from '../engine/import/importerutils.js';
import { AddDiv, CreateDomElement } from '../engine/viewer/domutils.js';
import { ButtonDialog } from './dialog.js';
+import { Loc } from '../engine/core/localization.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 (Loc ('Open from url'), [
{
- name : 'Cancel',
+ name : Loc ('Cancel'),
subClass : 'outline',
onClick () {
dialog.Close ();
}
},
{
- name : 'OK',
+ name : Loc ('OK'),
onClick () {
let urls = [];
ReadLines (urlsTextArea.value, (line) => {
@@ -26,7 +27,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 = Loc ('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..0feb5b04 100644
--- a/source/website/sharingdialog.js
+++ b/source/website/sharingdialog.js
@@ -6,6 +6,7 @@ import { ShowMessageDialog } from './dialogs.js';
import { ButtonDialog } from './dialog.js';
import { CopyToClipboard } from './utils.js';
import { HandleEvent } from './eventhandler.js';
+import { Loc } from '../engine/core/localization.js';
export function ShowSharingDialog (fileList, settings, viewer)
{
@@ -19,8 +20,8 @@ export function ShowSharingDialog (fileList, settings, viewer)
function AddCopyableTextInput (parentDiv, getText)
{
- let copyText = 'Copy';
- let copiedText = 'Copied';
+ let copyText = Loc ('Copy');
+ let copiedText = Loc ('Copied');
let container = AddDiv (parentDiv, 'ov_dialog_copyable_input');
let input = AddDomElement (container, 'input', null);
input.setAttribute ('type', 'text');
@@ -47,7 +48,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', Loc ('Sharing Link'));
let sharingLinkInput = AddCopyableTextInput (section, () => {
HandleEvent ('model_shared', 'sharing_link');
return GetSharingLink (modelFiles);
@@ -88,13 +89,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', Loc ('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, Loc ('Use customized settings', 'embed_current_settings'), (checked) => {
useCurrentSettings = checked;
embeddingCodeInput.value = GetEmbeddingCode (modelFiles, useCurrentSettings, settings, viewer);
});
@@ -104,8 +105,8 @@ export function ShowSharingDialog (fileList, settings, viewer)
if (!fileList.IsOnlyUrlSource ()) {
return ShowMessageDialog (
- 'Sharing Failed',
- 'Sharing works only if you load files by url. Please upload your model files to a web server, open them by url, and try embedding again.',
+ Loc ('Sharing Failed'),
+ Loc ('Sharing works only if you load files by url. Please upload your model files to a web server, open them by url, and try embedding again.'),
null
);
}
@@ -120,9 +121,9 @@ export function ShowSharingDialog (fileList, settings, viewer)
}
let dialog = new ButtonDialog ();
- let contentDiv = dialog.Init ('Share', [
+ let contentDiv = dialog.Init (Loc ('Share'), [
{
- name : 'Close',
+ name : Loc ('Close'),
onClick () {
dialog.Close ();
}
diff --git a/source/website/sidebardetailspanel.js b/source/website/sidebardetailspanel.js
index 73211bc1..294331b6 100644
--- a/source/website/sidebardetailspanel.js
+++ b/source/website/sidebardetailspanel.js
@@ -10,22 +10,23 @@ import { GetFileName, IsUrl } from '../engine/io/fileutils.js';
import { MaterialSource, MaterialType } from '../engine/model/material.js';
import { RGBColorToHexString } from '../engine/model/color.js';
import { Unit } from '../engine/model/unit.js';
+import { Loc } from '../engine/core/localization.js';
function UnitToString (unit)
{
switch (unit) {
case Unit.Millimeter:
- return 'Millimeter';
+ return Loc ('Millimeter');
case Unit.Centimeter:
- return 'Centimeter';
+ return Loc ('Centimeter');
case Unit.Meter:
- return 'Meter';
+ return Loc ('Meter');
case Unit.Inch:
- return 'Inch';
+ return Loc ('Inch');
case Unit.Foot:
- return 'Foot';
+ return Loc ('Foot');
}
- return 'Unknown';
+ return Loc ('Unknown');
}
export class SidebarDetailsPanel extends SidebarPanel
@@ -37,7 +38,7 @@ export class SidebarDetailsPanel extends SidebarPanel
GetName ()
{
- return 'Details';
+ return Loc ('Details');
}
GetIcon ()
@@ -52,29 +53,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, Loc ('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, Loc ('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, Loc ('Triangles'), triangleCount));
}
if (unit !== Unit.Unknown) {
- this.AddProperty (table, new Property (PropertyType.Text, 'Unit', UnitToString (unit)));
+ this.AddProperty (table, new Property (PropertyType.Text, Loc ('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, Loc ('Size X'), size.x));
+ this.AddProperty (table, new Property (PropertyType.Number, Loc ('Size Y'), size.y));
+ this.AddProperty (table, new Property (PropertyType.Number, Loc ('Size Z'), size.z));
+ this.AddCalculatedProperty (table, Loc ('Volume'), () => {
if (!IsTwoManifold (object3D)) {
return null;
}
const volume = CalculateVolume (object3D);
return new Property (PropertyType.Number, null, volume);
});
- this.AddCalculatedProperty (table, 'Surface', () => {
+ this.AddCalculatedProperty (table, Loc ('Surface'), () => {
const surfaceArea = CalculateSurfaceArea (object3D);
return new Property (PropertyType.Number, null, surfaceArea);
});
@@ -107,35 +108,35 @@ export class SidebarDetailsPanel extends SidebarPanel
let table = AddDiv (this.contentDiv, 'ov_property_table');
let typeString = null;
if (material.type === MaterialType.Phong) {
- typeString = 'Phong';
+ typeString = Loc ('Phong');
} else if (material.type === MaterialType.Physical) {
- typeString = 'Physical';
+ typeString = Loc ('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) ? Loc ('Default') : Loc ('Model');
+ this.AddProperty (table, new Property (PropertyType.Text, Loc ('Source'), materialSource));
+ this.AddProperty (table, new Property (PropertyType.Text, Loc ('Type'), typeString));
if (material.vertexColors) {
- this.AddProperty (table, new Property (PropertyType.Text, 'Color', 'Vertex colors'));
+ this.AddProperty (table, new Property (PropertyType.Text, Loc ('Color'), Loc ('Vertex colors')));
} else {
- this.AddProperty (table, new Property (PropertyType.Color, 'Color', material.color));
+ this.AddProperty (table, new Property (PropertyType.Color, Loc ('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, Loc ('Ambient'), material.ambient));
+ this.AddProperty (table, new Property (PropertyType.Color, Loc ('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, Loc ('Metalness'), material.metalness));
+ this.AddProperty (table, new Property (PropertyType.Percent, Loc ('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, Loc ('Opacity'), material.opacity));
+ AddTextureMap (this, table, Loc ('Diffuse Map'), material.diffuseMap);
+ AddTextureMap (this, table, Loc ('Bump Map'), material.bumpMap);
+ AddTextureMap (this, table, Loc ('Normal Map'), material.normalMap);
+ AddTextureMap (this, table, Loc ('Emissive Map'), material.emissiveMap);
if (material.type === MaterialType.Phong) {
- AddTextureMap (this, table, 'Specular Map', material.specularMap);
+ AddTextureMap (this, table, Loc ('Specular Map'), material.specularMap);
} else if (material.type === MaterialType.Physical) {
- AddTextureMap (this, table, 'Metallic Map', material.metalnessMap);
+ AddTextureMap (this, table, Loc ('Metallic Map'), material.metalnessMap);
}
this.Resize ();
}
@@ -169,10 +170,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', Loc ('Calculate...'));
calculateButton.addEventListener ('click', () => {
ClearDomElement (valueColumn);
- valueColumn.innerHTML = 'Please wait...';
+ valueColumn.innerHTML = Loc ('Please wait...');
RunTaskAsync (() => {
let propertyValue = calculateValue ();
if (propertyValue === null) {
diff --git a/source/website/sidebarsettingspanel.js b/source/website/sidebarsettingspanel.js
index 5ed9008f..5332ee19 100644
--- a/source/website/sidebarsettingspanel.js
+++ b/source/website/sidebarsettingspanel.js
@@ -7,6 +7,7 @@ import { Settings } from './settings.js';
import { SidebarPanel } from './sidebarpanel.js';
import { ShadingType } from '../engine/threejs/threeutils.js';
import { ProjectionMode } from '../engine/viewer/camera.js';
+import { Loc } from '../engine/core/localization.js';
import * as Pickr from '@simonwep/pickr';
import '@simonwep/pickr/dist/themes/monolith.min.css';
@@ -194,7 +195,7 @@ class SettingsModelDisplaySection extends SettingsSection
{
constructor (parentDiv, settings)
{
- super (parentDiv, 'Model Display', settings);
+ super (parentDiv, Loc ('Model Display'), settings);
this.backgroundColorPicker = null;
@@ -219,7 +220,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, Loc ('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 +230,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, Loc ('Background Image'));
this.environmentMapPhongInput.addEventListener ('click', () => {
this.environmentMapPopup = new EnvironmentMapPopup ();
this.environmentMapPopup.ShowPopup (this.environmentMapPhongInput, ShadingType.Phong, this.settings, {
@@ -245,7 +246,7 @@ class SettingsModelDisplaySection extends SettingsSection
this.environmentMapPbrDiv = AddDiv (this.contentDiv, 'ov_sidebar_parameter');
this.environmentMapPbrInput = AddDiv (this.environmentMapPbrDiv, 'ov_sidebar_image_picker');
- AddDiv (this.environmentMapPbrDiv, null, 'Environment');
+ AddDiv (this.environmentMapPbrDiv, null, Loc ('Environment'));
this.environmentMapPbrInput.addEventListener ('click', () => {
this.environmentMapPopup = new EnvironmentMapPopup ();
this.environmentMapPopup.ShowPopup (this.environmentMapPbrInput, ShadingType.Physical, this.settings, {
@@ -263,7 +264,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', Loc ('Show Edges'));
this.edgeSettingsDiv = AddDiv (this.contentDiv, 'ov_sidebar_settings_padded');
this.edgeDisplayToggle.OnChange (() => {
@@ -281,11 +282,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, Loc ('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', Loc ('Edge Angle Threshold'));
this.thresholdSliderValue = AddDomElement (thresholdRow, 'span', 'ov_slider_label');
this.thresholdSlider.addEventListener ('input', () => {
this.thresholdSliderValue.innerHTML = this.thresholdSlider.value;
@@ -375,7 +376,7 @@ class SettingsImportParametersSection extends SettingsSection
{
constructor (parentDiv, settings)
{
- super (parentDiv, 'Import Settings', settings);
+ super (parentDiv, Loc ('Import Settings'), settings);
this.defaultColorPickerDiv = null;
this.defaultLineColorPickerDiv = null;
this.defaultColorPicker = null;
@@ -396,12 +397,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, Loc ('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, Loc ('Default Line Color'), this.settings.defaultLineColor, (r, g, b, a) => {
this.settings.defaultLineColor = new RGBColor (r, g, b);
this.callbacks.onDefaultColorChanged ();
});
@@ -465,7 +466,7 @@ export class SidebarSettingsPanel extends SidebarPanel
GetName ()
{
- return 'Settings';
+ return Loc ('Settings');
}
HasTitle ()
diff --git a/source/website/snapshotdialog.js b/source/website/snapshotdialog.js
index 26dd97c0..93c66644 100644
--- a/source/website/snapshotdialog.js
+++ b/source/website/snapshotdialog.js
@@ -4,6 +4,7 @@ import { ButtonDialog } from './dialog.js';
import { DownloadUrlAsFile } from './utils.js';
import { CookieGetBoolVal, CookieGetIntVal, CookieGetStringVal, CookieSetBoolVal, CookieSetIntVal, CookieSetStringVal } from './cookiehandler.js';
import { HandleEvent } from './eventhandler.js';
+import { Loc } from '../engine/core/localization.js';
export function ShowSnapshotDialog (viewer)
{
@@ -66,19 +67,19 @@ export function ShowSnapshotDialog (viewer)
let customIndex = 3;
let sizes = [
{
- name : 'Small (1280x720)',
+ name : Loc ('Small (1280x720)'),
size : [1280, 720]
},
{
- name : 'Medium (1920x1080)',
+ name : Loc ('Medium (1920x1080)'),
size : [1920, 1080]
},
{
- name : 'Large (2560x1440)',
+ name : Loc ('Large (2560x1440)'),
size : [2560, 1440]
},
{
- name : 'Custom',
+ name : Loc ('Custom'),
size : null,
widthInput : null,
heightInput : null
@@ -86,16 +87,16 @@ export function ShowSnapshotDialog (viewer)
];
let dialog = new ButtonDialog ();
- let contentDiv = dialog.Init ('Create Snapshot', [
+ let contentDiv = dialog.Init (Loc ('Create Snapshot'), [
{
- name : 'Cancel',
+ name : Loc ('Cancel'),
subClass : 'outline',
onClick () {
dialog.Close ();
}
},
{
- name : 'Create',
+ name : Loc ('Create'),
onClick () {
dialog.Close ();
HandleEvent ('snapshot_created', sizes[selectedIndex].name);
@@ -135,11 +136,11 @@ export function ShowSnapshotDialog (viewer)
});
}
- customSize.widthInput = AddWidthHeightNumberInput (optionsDiv, 'Width', (val) => {
+ customSize.widthInput = AddWidthHeightNumberInput (optionsDiv, Loc ('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, Loc ('Height'), (val) => {
UpdatePreview (viewer, previewImage, GetSize (sizes, selectedIndex), isTransparent);
CookieSetIntVal ('ov_snapshot_custom_height', val);
});
@@ -149,7 +150,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', Loc ('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..ed744a2c 100644
--- a/source/website/threemodelloaderui.js
+++ b/source/website/threemodelloaderui.js
@@ -4,6 +4,7 @@ import { ShowMessageDialog } from './dialogs.js';
import { ButtonDialog, ProgressDialog } from './dialog.js';
import { AddSvgIconElement } from './utils.js';
import { ImportErrorCode } from '../engine/import/importer.js';
+import { Loc } from '../engine/core/localization.js';
export class ThreeModelLoaderUI
{
@@ -25,7 +26,7 @@ export class ThreeModelLoaderUI
this.CloseDialogIfOpen ();
callbacks.onStart ();
progressDialog = new ProgressDialog ();
- progressDialog.Init ('Loading Model');
+ progressDialog.Init (Loc ('Loading Model'));
progressDialog.Open ();
},
onFileListProgress : (current, total) => {
@@ -40,10 +41,10 @@ export class ThreeModelLoaderUI
});
},
onImportStart : () => {
- progressDialog.SetText ('Importing Model');
+ progressDialog.SetText (Loc ('Importing Model'));
},
onVisualizationStart : () => {
- progressDialog.SetText ('Visualizing Model');
+ progressDialog.SetText (Loc ('Visualizing Model'));
},
onModelFinished : (importResult, threeObject) => {
progressDialog.Close ();
@@ -74,26 +75,26 @@ export class ThreeModelLoaderUI
{
if (importError.code === ImportErrorCode.NoImportableFile) {
return ShowMessageDialog (
- 'Something went wrong',
- 'No importable file found.',
+ Loc ('Something went wrong'),
+ Loc ('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.'
+ Loc ('Something went wrong'),
+ Loc ('Failed to load file for import.'),
+ Loc ('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.',
+ Loc ('Something went wrong'),
+ Loc ('Failed to import model.'),
importError.message
);
} else {
return ShowMessageDialog (
- 'Something went wrong',
- 'Unknown error.',
+ Loc ('Something went wrong'),
+ Loc ('Unknown error.'),
null
);
}
@@ -102,9 +103,9 @@ export class ThreeModelLoaderUI
ShowFileSelectorDialog (fileNames, onSelect)
{
let dialog = new ButtonDialog ();
- let contentDiv = dialog.Init ('Select Model', [
+ let contentDiv = dialog.Init (Loc ('Select Model'), [
{
- name : 'Cancel',
+ name : Loc ('Cancel'),
subClass : 'outline',
onClick () {
dialog.Close ();
@@ -115,7 +116,7 @@ export class ThreeModelLoaderUI
onSelect (null);
});
- let text = 'Multiple importable models found. Select the model you would like to import from the list below.';
+ let text = Loc ('Multiple importable models found. Select the model you would like to import from the list below.');
AddDiv (contentDiv, 'ov_dialog_message', text);
let fileListSection = AddDiv (contentDiv, 'ov_dialog_section');
diff --git a/source/website/utils.js b/source/website/utils.js
index a51592f8..2a6eaa38 100644
--- a/source/website/utils.js
+++ b/source/website/utils.js
@@ -1,6 +1,7 @@
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 { Loc } from '../engine/core/localization.js';
export function GetNameOrDefault (originalName, defaultName)
{
@@ -12,18 +13,18 @@ export function GetNameOrDefault (originalName, defaultName)
export function GetNodeName (originalName)
{
- return GetNameOrDefault (originalName, 'No Name');
+ return GetNameOrDefault (originalName, Loc ('No Name'));
}
export function GetMeshName (originalNodeName, originalMeshName)
{
let originalName = (originalNodeName.length > 0 ? originalNodeName : originalMeshName);
- return GetNameOrDefault (originalName, 'No Name');
+ return GetNameOrDefault (originalName, Loc ('No Name'));
}
export function GetMaterialName (originalName)
{
- return GetNameOrDefault (originalName, 'No Name');
+ return GetNameOrDefault (originalName, Loc ('No Name'));
}
export function IsHoverEnabled ()
diff --git a/source/website/website.js b/source/website/website.js
index c75450c4..45c38de8 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 { Loc } from '../engine/core/localization.js';
const WebsiteUIState =
{
@@ -338,7 +339,7 @@ export class Website
let items = [];
if (meshUserData === null) {
items.push ({
- name : 'Fit model to window',
+ name : Loc ('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 : Loc ('Show all meshes'),
icon : 'visible',
onClick : () => {
this.navigator.ShowAllMeshes (true);
@@ -355,14 +356,14 @@ export class Website
}
} else {
items.push ({
- name : 'Hide mesh',
+ name : Loc ('Hide mesh'),
icon : 'hidden',
onClick : () => {
this.navigator.ToggleMeshVisibility (meshUserData.originalMeshInstance.id);
}
});
items.push ({
- name : 'Fit mesh to window',
+ name : Loc ('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 : isMeshIsolated ? Loc ('Remove isolation') : Loc ('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', Loc ('Open from your device'), [], () => {
this.OpenFileBrowserDialog ();
});
- AddButton (this.toolbar, 'open_url', 'Open from url', [], () => {
+ AddButton (this.toolbar, 'open_url', Loc ('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', Loc ('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', Loc ('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', Loc ('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', Loc ('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'], [Loc ('Fixed up vector'), Loc ('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'], [Loc ('Perspective camera'), Loc ('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) => {
+ let measureToolButton = AddPushButton (this.toolbar, 'measure', Loc ('Measure'), ['only_full_width', 'only_on_model'], (isSelected) => {
HandleEvent ('measure_tool_activated', isSelected ? 'on' : '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', Loc ('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', Loc ('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', Loc ('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', Loc ('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'], [Loc ('Dark mode'), Loc ('Light mode')], selectedTheme, ['align_right'], (buttonIndex) => {
if (buttonIndex === 0) {
this.settings.themeId = Theme.Dark;
} else if (buttonIndex === 1) {
@@ -967,10 +968,10 @@ 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 text = Loc ('This website uses cookies to offer you better user experience. See the details at the Cookies Policy page.');
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', Loc ('Accept'));
acceptButton.addEventListener ('click', () => {
CookieSetBoolVal ('ov_cookie_consent', true);
popupDiv.remove ();