Add localization technology to the engine.
This commit is contained in:
parent
9156b9172a
commit
449ce84bcd
@ -28,6 +28,13 @@ export function IsObjectEmpty (obj)
|
||||
return Object.keys (obj).length === 0;
|
||||
}
|
||||
|
||||
export function FormatString (template, ...args)
|
||||
{
|
||||
return template.replace (/{([0-9]+)}/g, (match, index) => {
|
||||
return args[index] === undefined ? match : args[index];
|
||||
});
|
||||
}
|
||||
|
||||
export function EscapeHtmlChars (str)
|
||||
{
|
||||
return str.replace (/</g, '<').replace (/>/g, '>');
|
||||
|
||||
30
source/engine/core/localization.js
Normal file
30
source/engine/core/localization.js
Normal file
@ -0,0 +1,30 @@
|
||||
import { FormatString } from './core.js';
|
||||
|
||||
let gLocalizedStrings = null;
|
||||
let gLanguageCode = null;
|
||||
|
||||
export function SetLocalizedStrings (localizedStrings)
|
||||
{
|
||||
gLocalizedStrings = localizedStrings;
|
||||
}
|
||||
|
||||
export function SetLanguageCode (languageCode)
|
||||
{
|
||||
gLanguageCode = languageCode;
|
||||
}
|
||||
|
||||
export function Loc (str)
|
||||
{
|
||||
if (gLocalizedStrings === null || gLanguageCode === null) {
|
||||
return str;
|
||||
}
|
||||
if (!gLocalizedStrings[str] || !gLocalizedStrings[str][gLanguageCode]) {
|
||||
return str;
|
||||
}
|
||||
return gLocalizedStrings[str][gLanguageCode];
|
||||
}
|
||||
|
||||
export function FLoc (str, ...args)
|
||||
{
|
||||
return FormatString (Loc (str), ...args);
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
import { ArrayBufferToUtf8String, Utf8StringToArrayBuffer } from '../io/bufferutils.js';
|
||||
import { Loc } from '../core/localization.js';
|
||||
|
||||
export class ExportedFile
|
||||
{
|
||||
@ -68,12 +69,12 @@ export class ExporterBase
|
||||
|
||||
GetExportedMaterialName (originalName)
|
||||
{
|
||||
return this.GetExportedName (originalName, 'Material');
|
||||
return this.GetExportedName (originalName, Loc ('Material'));
|
||||
}
|
||||
|
||||
GetExportedMeshName (originalName)
|
||||
{
|
||||
return this.GetExportedName (originalName, 'Mesh');
|
||||
return this.GetExportedName (originalName, Loc ('Mesh'));
|
||||
}
|
||||
|
||||
GetExportedName (originalName, defaultName)
|
||||
|
||||
@ -14,6 +14,7 @@ import { TextureMap } from '../model/material.js';
|
||||
import { Mesh } from '../model/mesh.js';
|
||||
import { Line } from '../model/line.js';
|
||||
import { ArrayToCoord3D } from '../geometry/coord3d.js';
|
||||
import { Loc } from '../core/localization.js';
|
||||
|
||||
export class Importer3dm extends ImporterBase
|
||||
{
|
||||
@ -55,7 +56,7 @@ export class Importer3dm extends ImporterBase
|
||||
onFinish ();
|
||||
});
|
||||
}).catch (() => {
|
||||
this.SetError ('Failed to load rhino3dm.');
|
||||
this.SetError (Loc ('Failed to load rhino3dm.'));
|
||||
onFinish ();
|
||||
});
|
||||
} else {
|
||||
@ -68,12 +69,12 @@ export class Importer3dm extends ImporterBase
|
||||
{
|
||||
let rhinoDoc = this.rhino.File3dm.fromByteArray (fileContent);
|
||||
if (rhinoDoc === null) {
|
||||
this.SetError ('Failed to read Rhino file.');
|
||||
this.SetError (Loc ('Failed to read Rhino file.'));
|
||||
return;
|
||||
}
|
||||
this.ImportRhinoDocument (rhinoDoc);
|
||||
if (IsModelEmpty (this.model)) {
|
||||
this.SetError ('The model doesn\'t contain any 3D meshes. Try to save the model while you are in shaded view in Rhino.');
|
||||
this.SetError (Loc ('The model doesn\'t contain any 3D meshes. Try to save the model while you are in shaded view in Rhino.'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,7 +106,7 @@ export class Importer3dm extends ImporterBase
|
||||
{
|
||||
let docStrings = rhinoDoc.strings ();
|
||||
if (docStrings.count > 0) {
|
||||
let propertyGroup = new PropertyGroup ('Document user texts');
|
||||
let propertyGroup = new PropertyGroup (Loc ('Document user texts'));
|
||||
for (let i = 0; i < docStrings.count; i++) {
|
||||
let docString = docStrings.get (i);
|
||||
propertyGroup.AddProperty (new Property (PropertyType.Text, docString[0], docString[1]));
|
||||
@ -238,7 +239,7 @@ export class Importer3dm extends ImporterBase
|
||||
|
||||
let userStrings = rhinoAttributes.getUserStrings ();
|
||||
if (userStrings.length > 0) {
|
||||
let propertyGroup = new PropertyGroup ('User texts');
|
||||
let propertyGroup = new PropertyGroup (Loc ('User texts'));
|
||||
for (let i = 0; i < userStrings.length; i++) {
|
||||
let userString = userStrings[i];
|
||||
propertyGroup.AddProperty (new Property (PropertyType.Text, userString[0], userString[1]));
|
||||
|
||||
@ -2,6 +2,7 @@ import { Direction } from '../geometry/geometry.js';
|
||||
import { Model } from '../model/model.js';
|
||||
import { FinalizeModel } from '../model/modelfinalization.js';
|
||||
import { IsModelEmpty } from '../model/modelutils.js';
|
||||
import { Loc } from '../core/localization.js';
|
||||
|
||||
export class ImporterBase
|
||||
{
|
||||
@ -51,7 +52,7 @@ export class ImporterBase
|
||||
}
|
||||
|
||||
if (IsModelEmpty (this.model)) {
|
||||
this.SetError ('The model doesn\'t contain any meshes.');
|
||||
this.SetError (Loc ('The model doesn\'t contain any meshes.'));
|
||||
callbacks.onError ();
|
||||
callbacks.onComplete ();
|
||||
return;
|
||||
|
||||
@ -12,6 +12,7 @@ import { Transformation } from '../geometry/transformation.js';
|
||||
import { ColorToMaterialConverter } from './importerutils.js';
|
||||
import { Property, PropertyGroup, PropertyType } from '../model/property.js';
|
||||
import { Unit } from '../model/unit.js';
|
||||
import { Loc } from '../core/localization.js';
|
||||
|
||||
export class ImporterBim extends ImporterBase
|
||||
{
|
||||
@ -51,7 +52,7 @@ export class ImporterBim extends ImporterBase
|
||||
try {
|
||||
bimJson = JSON.parse (textContent);
|
||||
} catch (err) {
|
||||
this.SetError ('Failed to parse bim file.');
|
||||
this.SetError (Loc ('Failed to parse bim file.'));
|
||||
onFinish ();
|
||||
return;
|
||||
}
|
||||
@ -170,9 +171,9 @@ export class ImporterBim extends ImporterBase
|
||||
}
|
||||
|
||||
let info = source.info;
|
||||
let propertyGroup = new PropertyGroup ('Info');
|
||||
AddProperty (propertyGroup, 'Guid', source.guid);
|
||||
AddProperty (propertyGroup, 'Type', source.type);
|
||||
let propertyGroup = new PropertyGroup (Loc ('Info'));
|
||||
AddProperty (propertyGroup, Loc ('Guid'), source.guid);
|
||||
AddProperty (propertyGroup, Loc ('Type'), source.type);
|
||||
for (let propertyName in info) {
|
||||
if (Object.prototype.hasOwnProperty.call (info, propertyName)) {
|
||||
if (typeof info[propertyName] === 'string') {
|
||||
|
||||
@ -8,6 +8,7 @@ import { Node } from '../model/node.js';
|
||||
import { ColorToMaterialConverter } from './importerutils.js';
|
||||
import { RGBAColor } from '../model/color.js';
|
||||
import { Property, PropertyGroup, PropertyType } from '../model/property.js';
|
||||
import { Loc } from '../core/localization.js';
|
||||
|
||||
import * as fflate from 'fflate';
|
||||
|
||||
@ -105,7 +106,7 @@ class FreeCadDocument
|
||||
return false;
|
||||
}
|
||||
|
||||
this.properties = new PropertyGroup ('Properties');
|
||||
this.properties = new PropertyGroup (Loc ('Properties'));
|
||||
let documentElements = documentXml.getElementsByTagName ('Document');
|
||||
for (let documentElement of documentElements) {
|
||||
for (let childNode of documentElement.childNodes) {
|
||||
@ -140,7 +141,7 @@ class FreeCadDocument
|
||||
}
|
||||
|
||||
let object = this.objectData.get (name);
|
||||
object.properties = new PropertyGroup ('Properties');
|
||||
object.properties = new PropertyGroup (Loc ('Properties'));
|
||||
for (let childNode of objectElement.childNodes) {
|
||||
if (childNode.tagName === 'Properties') {
|
||||
this.GetPropertiesFromElement (childNode, object.properties);
|
||||
@ -322,7 +323,7 @@ export class ImporterFcstd extends ImporterBase
|
||||
{
|
||||
let result = this.document.Init (fileContent);
|
||||
if (result === DocumentInitResult.NoDocumentXml) {
|
||||
this.SetError ('No Document.xml found.');
|
||||
this.SetError (Loc ('No Document.xml found.'));
|
||||
onFinish ();
|
||||
return;
|
||||
}
|
||||
@ -333,7 +334,7 @@ export class ImporterFcstd extends ImporterBase
|
||||
|
||||
let objectsToConvert = this.document.GetObjectListToConvert ();
|
||||
if (objectsToConvert.length === 0) {
|
||||
this.SetError ('No importable object found.');
|
||||
this.SetError (Loc ('No importable object found.'));
|
||||
onFinish ();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import { Node } from '../model/node.js';
|
||||
import { Property, PropertyGroup, PropertyType } from '../model/property.js';
|
||||
import { Triangle } from '../model/triangle.js';
|
||||
import { ImporterBase } from './importerbase.js';
|
||||
import { Loc, FLoc } from '../core/localization.js';
|
||||
|
||||
const GltfComponentType =
|
||||
{
|
||||
@ -287,7 +288,7 @@ class GltfExtensions
|
||||
callbacks.onSuccess ();
|
||||
});
|
||||
}).catch (() => {
|
||||
callbacks.onError ('Failed to load draco decoder.');
|
||||
callbacks.onError (Loc ('Failed to load draco decoder.'));
|
||||
});
|
||||
} else {
|
||||
callbacks.onSuccess ();
|
||||
@ -527,7 +528,7 @@ export class ImporterGltf extends ImporterBase
|
||||
let textContent = ArrayBufferToUtf8String (fileContent);
|
||||
let gltf = JSON.parse (textContent);
|
||||
if (gltf.asset.version !== '2.0') {
|
||||
this.SetError ('Invalid glTF version.');
|
||||
this.SetError (Loc ('Invalid glTF version.'));
|
||||
onFinish ();
|
||||
return;
|
||||
}
|
||||
@ -545,7 +546,7 @@ export class ImporterGltf extends ImporterBase
|
||||
}
|
||||
}
|
||||
if (buffer === null) {
|
||||
this.SetError ('One of the requested buffers is missing.');
|
||||
this.SetError (Loc ('One of the requested buffers is missing.'));
|
||||
onFinish ();
|
||||
return;
|
||||
}
|
||||
@ -571,19 +572,19 @@ export class ImporterGltf extends ImporterBase
|
||||
let reader = new BinaryReader (fileContent, true);
|
||||
let magic = reader.ReadUnsignedInteger32 ();
|
||||
if (magic !== GltfConstants.GLTF_STRING) {
|
||||
this.SetError ('Invalid glTF file.');
|
||||
this.SetError (Loc ('Invalid glTF file.'));
|
||||
onFinish ();
|
||||
return;
|
||||
}
|
||||
let version = reader.ReadUnsignedInteger32 ();
|
||||
if (version !== 2) {
|
||||
this.SetError ('Invalid glTF version.');
|
||||
this.SetError (Loc ('Invalid glTF version.'));
|
||||
onFinish ();
|
||||
return;
|
||||
}
|
||||
let length = reader.ReadUnsignedInteger32 ();
|
||||
if (length !== reader.GetByteLength ()) {
|
||||
this.SetError ('Invalid glTF file.');
|
||||
this.SetError (Loc ('Invalid glTF file.'));
|
||||
onFinish ();
|
||||
return;
|
||||
}
|
||||
@ -608,7 +609,7 @@ export class ImporterGltf extends ImporterBase
|
||||
{
|
||||
let unsupportedExtensions = this.gltfExtensions.GetUnsupportedExtensions (gltf.extensionsRequired);
|
||||
if (unsupportedExtensions.length > 0) {
|
||||
this.SetError ('Unsupported extension: ' + unsupportedExtensions.join (', ') + '.');
|
||||
this.SetError (FLoc ('Unsupported extension: {0}.', unsupportedExtensions.join (', ')));
|
||||
onFinish ();
|
||||
return;
|
||||
}
|
||||
@ -641,7 +642,7 @@ export class ImporterGltf extends ImporterBase
|
||||
}
|
||||
}
|
||||
|
||||
this.ImportProperties (this.model, gltf.asset, 'Asset properties');
|
||||
this.ImportProperties (this.model, gltf.asset, Loc ('Asset properties'));
|
||||
this.ImportScene (gltf);
|
||||
}
|
||||
|
||||
@ -809,7 +810,7 @@ export class ImporterGltf extends ImporterBase
|
||||
this.ImportPrimitive (gltf, primitive, mesh);
|
||||
}
|
||||
|
||||
this.ImportProperties (mesh, gltfMesh.extras, 'Mesh properties');
|
||||
this.ImportProperties (mesh, gltfMesh.extras, Loc ('Mesh properties'));
|
||||
}
|
||||
|
||||
ImportPrimitive (gltf, primitive, mesh)
|
||||
@ -1006,7 +1007,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, Loc ('Scene properties'));
|
||||
}
|
||||
|
||||
ImportNode (gltf, gltfNode, parentNode)
|
||||
@ -1058,7 +1059,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, Loc ('Node properties'));
|
||||
node.AddMeshIndex (gltfNode.mesh);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import { Property, PropertyGroup, PropertyType } from '../model/property.js';
|
||||
import { Triangle } from '../model/triangle.js';
|
||||
import { ImporterBase } from './importerbase.js';
|
||||
import { ColorToMaterialConverter } from './importerutils.js';
|
||||
import { Loc, FLoc } from '../core/localization.js';
|
||||
|
||||
export class ImporterIfc extends ImporterBase
|
||||
{
|
||||
@ -50,7 +51,7 @@ export class ImporterIfc extends ImporterBase
|
||||
onFinish ();
|
||||
});
|
||||
}).catch (() => {
|
||||
this.SetError ('Failed to load web-ifc.');
|
||||
this.SetError (Loc ('Failed to load web-ifc.'));
|
||||
onFinish ();
|
||||
});
|
||||
} else {
|
||||
@ -79,7 +80,7 @@ export class ImporterIfc extends ImporterBase
|
||||
ImportIfcMesh (modelID, ifcMesh)
|
||||
{
|
||||
let mesh = new Mesh ();
|
||||
mesh.SetName ('Mesh ' + ifcMesh.expressID.toString ());
|
||||
mesh.SetName (FLoc ('Mesh {0}', ifcMesh.expressID.toString ()));
|
||||
|
||||
let vertexOffset = 0;
|
||||
const ifcGeometries = ifcMesh.geometries;
|
||||
@ -170,11 +171,11 @@ export class ImporterIfc extends ImporterBase
|
||||
break;
|
||||
case 'IfcBoolean':
|
||||
case 'IfcLogical':
|
||||
strValue = 'Unknown';
|
||||
strValue = Loc ('Unknown');
|
||||
if (property.NominalValue.value === 'T') {
|
||||
strValue = 'True';
|
||||
strValue = Loc ('True');
|
||||
} else if (property.NominalValue.value === 'F') {
|
||||
strValue = 'False';
|
||||
strValue = Loc ('False');
|
||||
}
|
||||
elemProperty = new Property (PropertyType.Text, propertyName, strValue);
|
||||
break;
|
||||
|
||||
@ -9,6 +9,7 @@ import { Mesh } from '../model/mesh.js';
|
||||
import { Triangle } from '../model/triangle.js';
|
||||
import { ImporterBase } from './importerbase.js';
|
||||
import { NameFromLine, ParametersFromLine, ReadLines, UpdateMaterialTransparency } from './importerutils.js';
|
||||
import { Loc } from '../core/localization.js';
|
||||
|
||||
class ObjMeshConverter
|
||||
{
|
||||
@ -398,7 +399,7 @@ export class ImporterObj extends ImporterBase
|
||||
let vertexIndex = this.GetRelativeIndex (parseInt (vertexParams[0], 10), this.globalVertices.length);
|
||||
let meshVertexIndex = this.currentMeshConverter.AddVertex (vertexIndex, this.globalVertices);
|
||||
if (meshVertexIndex === null) {
|
||||
this.SetError ('Invalid vertex index.');
|
||||
this.SetError (Loc ('Invalid vertex index.'));
|
||||
break;
|
||||
}
|
||||
vertices.push (meshVertexIndex);
|
||||
@ -442,7 +443,7 @@ export class ImporterObj extends ImporterBase
|
||||
let v1 = this.currentMeshConverter.AddVertex (vertices[i + 1], this.globalVertices);
|
||||
let v2 = this.currentMeshConverter.AddVertex (vertices[i + 2], this.globalVertices);
|
||||
if (v0 === null || v1 === null || v2 === null) {
|
||||
this.SetError ('Invalid vertex index.');
|
||||
this.SetError (Loc ('Invalid vertex index.'));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -453,7 +454,7 @@ export class ImporterObj extends ImporterBase
|
||||
let c1 = this.currentMeshConverter.AddVertexColor (colors[i + 1], this.globalVertexColors);
|
||||
let c2 = this.currentMeshConverter.AddVertexColor (colors[i + 2], this.globalVertexColors);
|
||||
if (c0 === null || c1 === null || c2 === null) {
|
||||
this.SetError ('Invalid vertex color index.');
|
||||
this.SetError (Loc ('Invalid vertex color index.'));
|
||||
break;
|
||||
}
|
||||
triangle.SetVertexColors (c0, c1, c2);
|
||||
@ -464,7 +465,7 @@ export class ImporterObj extends ImporterBase
|
||||
let n1 = this.currentMeshConverter.AddNormal (normals[i + 1], this.globalNormals);
|
||||
let n2 = this.currentMeshConverter.AddNormal (normals[i + 2], this.globalNormals);
|
||||
if (n0 === null || n1 === null || n2 === null) {
|
||||
this.SetError ('Invalid normal index.');
|
||||
this.SetError (Loc ('Invalid normal index.'));
|
||||
break;
|
||||
}
|
||||
triangle.SetNormals (n0, n1, n2);
|
||||
@ -475,7 +476,7 @@ export class ImporterObj extends ImporterBase
|
||||
let u1 = this.currentMeshConverter.AddUV (uvs[i + 1], this.globalUvs);
|
||||
let u2 = this.currentMeshConverter.AddUV (uvs[i + 2], this.globalUvs);
|
||||
if (u0 === null || u1 === null || u2 === null) {
|
||||
this.SetError ('Invalid uv index.');
|
||||
this.SetError (Loc ('Invalid uv index.'));
|
||||
break;
|
||||
}
|
||||
triangle.SetTextureUVs (u0, u1, u2);
|
||||
|
||||
@ -6,6 +6,7 @@ import { ConvertThreeGeometryToMesh } from '../threejs/threeutils.js';
|
||||
import { ImporterBase } from './importerbase.js';
|
||||
import { ColorToMaterialConverter } from './importerutils.js';
|
||||
import { Unit } from '../model/unit.js';
|
||||
import { Loc } from '../core/localization.js';
|
||||
|
||||
export class ImporterOcct extends ImporterBase
|
||||
{
|
||||
@ -46,7 +47,7 @@ export class ImporterOcct extends ImporterBase
|
||||
this.ImportResultJson (ev.data, onFinish);
|
||||
});
|
||||
this.worker.addEventListener ('error', (ev) => {
|
||||
this.SetError ('Failed to load occt-import-js.');
|
||||
this.SetError (Loc ('Failed to load occt-import-js.'));
|
||||
onFinish ();
|
||||
});
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import { Mesh } from '../model/mesh.js';
|
||||
import { Triangle } from '../model/triangle.js';
|
||||
import { ImporterBase } from './importerbase.js';
|
||||
import { ParametersFromLine, ReadLines, UpdateMaterialTransparency } from './importerutils.js';
|
||||
import { Loc, FLoc } from '../core/localization.js';
|
||||
|
||||
const PlyHeaderCheckResult =
|
||||
{
|
||||
@ -113,11 +114,12 @@ class PlyMaterialHandler
|
||||
|
||||
GetMaterialIndexByColor (color)
|
||||
{
|
||||
let materialName = 'Color ' +
|
||||
IntegerToHexString (color[0]) +
|
||||
IntegerToHexString (color[1]) +
|
||||
IntegerToHexString (color[2]) +
|
||||
IntegerToHexString (color[3]);
|
||||
let materialName = FLoc ('Color {0}{1}{2}{3}',
|
||||
IntegerToHexString (color[0]),
|
||||
IntegerToHexString (color[1]),
|
||||
IntegerToHexString (color[2]),
|
||||
IntegerToHexString (color[3])
|
||||
);
|
||||
|
||||
if (this.colorToMaterial.has (materialName)) {
|
||||
return this.colorToMaterial.get (materialName);
|
||||
@ -177,11 +179,11 @@ export class ImporterPly extends ImporterBase
|
||||
}
|
||||
} else {
|
||||
if (checkResult === PlyHeaderCheckResult.NoVertices) {
|
||||
this.SetError ('The model contains no vertices.');
|
||||
this.SetError (Loc ('The model contains no vertices.'));
|
||||
} else if (checkResult === PlyHeaderCheckResult.NoFaces) {
|
||||
this.SetError ('The model contains no faces.');
|
||||
this.SetError (Loc ('The model contains no faces.'));
|
||||
} else {
|
||||
this.SetError ('Invalid header information.');
|
||||
this.SetError (Loc ('Invalid header information.'));
|
||||
}
|
||||
}
|
||||
onFinish ();
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { IsDefined, ValueOrDefault, CopyObjectAttributes, IsObjectEmpty, EscapeHtmlChars } from './core/core.js';
|
||||
import { IsDefined, ValueOrDefault, CopyObjectAttributes, IsObjectEmpty, FormatString, EscapeHtmlChars } from './core/core.js';
|
||||
import { EventNotifier } from './core/eventnotifier.js';
|
||||
import { SetLocalizedStrings, SetLanguageCode, Loc, FLoc } from './core/localization.js';
|
||||
import { TaskRunner, RunTaskAsync, RunTasks, RunTasksBatch, WaitWhile } from './core/taskrunner.js';
|
||||
import { Exporter } from './export/exporter.js';
|
||||
import { Exporter3dm } from './export/exporter3dm.js';
|
||||
@ -80,8 +81,13 @@ export {
|
||||
ValueOrDefault,
|
||||
CopyObjectAttributes,
|
||||
IsObjectEmpty,
|
||||
FormatString,
|
||||
EscapeHtmlChars,
|
||||
EventNotifier,
|
||||
SetLocalizedStrings,
|
||||
SetLanguageCode,
|
||||
Loc,
|
||||
FLoc,
|
||||
TaskRunner,
|
||||
RunTaskAsync,
|
||||
RunTasks,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { EscapeHtmlChars } from '../core/core.js';
|
||||
import { RGBColorToHexString } from './color.js';
|
||||
import { Loc } from '../core/localization.js';
|
||||
|
||||
export const PropertyType =
|
||||
{
|
||||
@ -76,7 +77,7 @@ export function PropertyToString (property)
|
||||
maximumFractionDigits: 2
|
||||
});
|
||||
} else if (property.type === PropertyType.Boolean) {
|
||||
return property.value ? 'True' : 'False';
|
||||
return property.value ? Loc ('True') : Loc ('False');
|
||||
} else if (property.type === PropertyType.Percent) {
|
||||
return parseInt (property.value * 100, 10).toString () + '%';
|
||||
} else if (property.type === PropertyType.Color) {
|
||||
|
||||
@ -7,6 +7,7 @@ import { ParameterConverter } from '../parameters/parameterlist.js';
|
||||
import { ThreeModelLoader } from '../threejs/threemodelloader.js';
|
||||
import { Viewer } from './viewer.js';
|
||||
import { EnvironmentSettings } from './shadingmodel.js';
|
||||
import { Loc } from '../core/localization.js';
|
||||
|
||||
/**
|
||||
* This is the main object for embedding the viewer on a website.
|
||||
@ -124,7 +125,7 @@ export class EmbeddedViewer
|
||||
onLoadStart : () => {
|
||||
this.canvas.style.display = 'none';
|
||||
progressDiv = document.createElement ('div');
|
||||
progressDiv.innerHTML = 'Loading model...';
|
||||
progressDiv.innerHTML = Loc ('Loading model...');
|
||||
this.parentElement.appendChild (progressDiv);
|
||||
},
|
||||
onFileListProgress : (current, total) => {
|
||||
@ -132,10 +133,10 @@ export class EmbeddedViewer
|
||||
onFileLoadProgress : (current, total) => {
|
||||
},
|
||||
onImportStart : () => {
|
||||
progressDiv.innerHTML = 'Importing model...';
|
||||
progressDiv.innerHTML = Loc ('Importing model...');
|
||||
},
|
||||
onVisualizationStart : () => {
|
||||
progressDiv.innerHTML = 'Visualizing model...';
|
||||
progressDiv.innerHTML = Loc ('Visualizing model...');
|
||||
},
|
||||
onModelFinished : (importResult, threeObject) => {
|
||||
this.parentElement.removeChild (progressDiv);
|
||||
@ -161,13 +162,13 @@ export class EmbeddedViewer
|
||||
this.viewer.Render ();
|
||||
},
|
||||
onLoadError : (importError) => {
|
||||
let message = 'Unknown error.';
|
||||
let message = Loc ('Unknown error.');
|
||||
if (importError.code === ImportErrorCode.NoImportableFile) {
|
||||
message = 'No importable file found.';
|
||||
message = Loc ('No importable file found.');
|
||||
} else if (importError.code === ImportErrorCode.FailedToLoadFile) {
|
||||
message = 'Failed to load file for import.';
|
||||
message = Loc ('Failed to load file for import.');
|
||||
} else if (importError.code === ImportErrorCode.ImportFailed) {
|
||||
message = 'Failed to import model.';
|
||||
message = Loc ('Failed to import model.');
|
||||
}
|
||||
if (importError.message !== null) {
|
||||
message += ' (' + importError.message + ')';
|
||||
|
||||
@ -67,6 +67,36 @@ describe ('Core', function () {
|
||||
assert.ok (!en.HasEventListener ('third_event'));
|
||||
assert.strictEqual (sumValues, 90);
|
||||
});
|
||||
|
||||
it ('Localization', function () {
|
||||
assert.strictEqual (OV.Loc ('Test'), 'Test');
|
||||
assert.strictEqual (OV.FLoc ('Test {0}', '1'), 'Test 1');
|
||||
OV.SetLocalizedStrings ({
|
||||
'Test' : {
|
||||
'hu': 'Teszt'
|
||||
},
|
||||
'Test {0}' : {
|
||||
'hu': 'Teszt {0}'
|
||||
},
|
||||
'Test {0} {0}' : {
|
||||
'hu': 'Teszt {0} {0}'
|
||||
},
|
||||
'Test {0} {0} {1}' : {
|
||||
'hu': 'Teszt {0} {0} {1}'
|
||||
}
|
||||
});
|
||||
OV.SetLanguageCode ('not_existing');
|
||||
assert.strictEqual (OV.Loc ('Test'), 'Test');
|
||||
|
||||
OV.SetLanguageCode ('hu');
|
||||
assert.strictEqual (OV.Loc ('Test'), 'Teszt');
|
||||
assert.strictEqual (OV.FLoc ('Test {0}', 'a'), 'Teszt a');
|
||||
assert.strictEqual (OV.FLoc ('Test {0} {0}', 'a'), 'Teszt a a');
|
||||
assert.strictEqual (OV.FLoc ('Test {0} {0} {1}', 'a', 'b'), 'Teszt a a b');
|
||||
|
||||
OV.SetLocalizedStrings (null);
|
||||
OV.SetLanguageCode (null);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user