Browse Source

Editor: Added localisation support.

Mr.doob 6 years ago
parent
commit
b2ce63ce2b

+ 1 - 0
editor/index.html

@@ -138,6 +138,7 @@
 		<script src="js/Sidebar.Animation.js"></script>
 		<script src="js/Sidebar.Script.js"></script>
 		<script src="js/Sidebar.History.js"></script>
+		<script src="js/Strings.js"></script>
 		<script src="js/Toolbar.js"></script>
 		<script src="js/Viewport.js"></script>
 		<script src="js/Viewport.Info.js"></script>

+ 2 - 0
editor/js/Config.js

@@ -7,6 +7,8 @@ var Config = function () {
 	var name = 'threejs-editor';
 
 	var storage = {
+		'language': 'en',
+
 		'autosave': true,
 		'theme': 'css/light.css',
 

+ 2 - 0
editor/js/Editor.js

@@ -75,6 +75,8 @@ var Editor = function () {
 	this.config = new Config();
 	this.history = new History( this );
 	this.storage = new Storage();
+	this.strings = new Strings( this.config );
+
 	this.loader = new Loader( this );
 
 	this.camera = this.DEFAULT_CAMERA.clone();

+ 20 - 18
editor/js/Menubar.Add.js

@@ -4,12 +4,14 @@
 
 Menubar.Add = function ( editor ) {
 
+	var strings = editor.strings;
+
 	var container = new UI.Panel();
 	container.setClass( 'menu' );
 
 	var title = new UI.Panel();
 	title.setClass( 'title' );
-	title.setTextContent( 'Add' );
+	title.setTextContent( strings.getKey( 'menubar/add' ) );
 	container.add( title );
 
 	var options = new UI.Panel();
@@ -20,7 +22,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Group' );
+	option.setTextContent( strings.getKey( 'menubar/add/group' ) );
 	option.onClick( function () {
 
 		var mesh = new THREE.Group();
@@ -39,7 +41,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Plane' );
+	option.setTextContent( strings.getKey( 'menubar/add/plane' )  );
 	option.onClick( function () {
 
 		var geometry = new THREE.PlaneBufferGeometry( 1, 1, 1, 1 );
@@ -56,7 +58,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Box' );
+	option.setTextContent( strings.getKey( 'menubar/add/box' )  );
 	option.onClick( function () {
 
 		var geometry = new THREE.BoxBufferGeometry( 1, 1, 1, 1, 1, 1 );
@@ -72,7 +74,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Circle' );
+	option.setTextContent( strings.getKey( 'menubar/add/circle' ) );
 	option.onClick( function () {
 
 		var geometry = new THREE.CircleBufferGeometry( 1, 8, 0, Math.PI * 2 );
@@ -88,7 +90,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Cylinder' );
+	option.setTextContent( strings.getKey( 'menubar/add/cylinder' )  );
 	option.onClick( function () {
 
 		var geometry = new THREE.CylinderBufferGeometry( 1, 1, 1, 8, 1, false, 0, Math.PI * 2 );
@@ -104,7 +106,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Sphere' );
+	option.setTextContent( strings.getKey( 'menubar/add/sphere' )  );
 	option.onClick( function () {
 
 		var geometry = new THREE.SphereBufferGeometry( 1, 8, 6, 0, Math.PI * 2, 0, Math.PI );
@@ -120,7 +122,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Icosahedron' );
+	option.setTextContent( strings.getKey( 'menubar/add/icosahedron' )  );
 	option.onClick( function () {
 
 		var geometry = new THREE.IcosahedronGeometry( 1, 0 );
@@ -136,7 +138,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Torus' );
+	option.setTextContent( strings.getKey( 'menubar/add/torus' )  );
 	option.onClick( function () {
 
 		var geometry = new THREE.TorusBufferGeometry( 1, 0.4, 8, 6, Math.PI * 2 );
@@ -152,7 +154,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'TorusKnot' );
+	option.setTextContent( strings.getKey( 'menubar/add/torusknot' )  );
 	option.onClick( function () {
 
 		var geometry = new THREE.TorusKnotBufferGeometry( 1, 0.4, 64, 8, 2, 3 );
@@ -197,7 +199,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Lathe' );
+	option.setTextContent( strings.getKey( 'menubar/add/lathe' )  );
 	option.onClick( function() {
 
 		var points = [
@@ -227,7 +229,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Sprite' );
+	option.setTextContent( strings.getKey( 'menubar/add/sprite' )  );
 	option.onClick( function () {
 
 		var sprite = new THREE.Sprite( new THREE.SpriteMaterial() );
@@ -246,7 +248,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'PointLight' );
+	option.setTextContent( strings.getKey( 'menubar/add/pointlight' )  );
 	option.onClick( function () {
 
 		var color = 0xffffff;
@@ -265,7 +267,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'SpotLight' );
+	option.setTextContent( strings.getKey( 'menubar/add/spotlight' )  );
 	option.onClick( function () {
 
 		var color = 0xffffff;
@@ -289,7 +291,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'DirectionalLight' );
+	option.setTextContent( strings.getKey( 'menubar/add/directionallight' )  );
 	option.onClick( function () {
 
 		var color = 0xffffff;
@@ -310,7 +312,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'HemisphereLight' );
+	option.setTextContent( strings.getKey( 'menubar/add/hemispherelight' )  );
 	option.onClick( function () {
 
 		var skyColor = 0x00aaff;
@@ -331,7 +333,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'AmbientLight' );
+	option.setTextContent( strings.getKey( 'menubar/add/ambientlight' )  );
 	option.onClick( function() {
 
 		var color = 0x222222;
@@ -352,7 +354,7 @@ Menubar.Add = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'PerspectiveCamera' );
+	option.setTextContent( strings.getKey( 'menubar/add/perspectivecamera' )  );
 	option.onClick( function() {
 
 		var camera = new THREE.PerspectiveCamera( 50, 1, 1, 10000 );

+ 9 - 7
editor/js/Menubar.Edit.js

@@ -4,12 +4,14 @@
 
 Menubar.Edit = function ( editor ) {
 
+	var strings = editor.strings;
+
 	var container = new UI.Panel();
 	container.setClass( 'menu' );
 
 	var title = new UI.Panel();
 	title.setClass( 'title' );
-	title.setTextContent( 'Edit' );
+	title.setTextContent( strings.getKey( 'menubar/edit' ) );
 	container.add( title );
 
 	var options = new UI.Panel();
@@ -20,7 +22,7 @@ Menubar.Edit = function ( editor ) {
 
 	var undo = new UI.Row();
 	undo.setClass( 'option' );
-	undo.setTextContent( 'Undo (Ctrl+Z)' );
+	undo.setTextContent( strings.getKey( 'menubar/edit/undo' ) );
 	undo.onClick( function () {
 
 		editor.undo();
@@ -32,7 +34,7 @@ Menubar.Edit = function ( editor ) {
 
 	var redo = new UI.Row();
 	redo.setClass( 'option' );
-	redo.setTextContent( 'Redo (Ctrl+Shift+Z)' );
+	redo.setTextContent( strings.getKey( 'menubar/edit/redo' ) );
 	redo.onClick( function () {
 
 		editor.redo();
@@ -44,7 +46,7 @@ Menubar.Edit = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Clear History' );
+	option.setTextContent( strings.getKey( 'menubar/edit/clear_history' ) );
 	option.onClick( function () {
 
 		if ( confirm( 'The Undo/Redo History will be cleared. Are you sure?' ) ) {
@@ -86,7 +88,7 @@ Menubar.Edit = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Clone' );
+	option.setTextContent( strings.getKey( 'menubar/edit/clone' ) );
 	option.onClick( function () {
 
 		var object = editor.selected;
@@ -104,7 +106,7 @@ Menubar.Edit = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Delete (Del)' );
+	option.setTextContent( strings.getKey( 'menubar/edit/delete' ) );
 	option.onClick( function () {
 
 		var object = editor.selected;
@@ -121,7 +123,7 @@ Menubar.Edit = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Minify Shaders' );
+	option.setTextContent( strings.getKey( 'menubar/edit/minify_shaders' ) );
 	option.onClick( function() {
 
 		var root = editor.selected || editor.scene;

+ 3 - 1
editor/js/Menubar.Examples.js

@@ -4,12 +4,14 @@
 
 Menubar.Examples = function ( editor ) {
 
+	var strings = editor.strings;
+
 	var container = new UI.Panel();
 	container.setClass( 'menu' );
 
 	var title = new UI.Panel();
 	title.setClass( 'title' );
-	title.setTextContent( 'Examples' );
+	title.setTextContent( strings.getKey( 'menubar/examples' ) );
 	container.add( title );
 
 	var options = new UI.Panel();

+ 13 - 12
editor/js/Menubar.File.js

@@ -15,13 +15,14 @@ Menubar.File = function ( editor ) {
 	//
 
 	var config = editor.config;
+	var strings = editor.strings;
 
 	var container = new UI.Panel();
 	container.setClass( 'menu' );
 
 	var title = new UI.Panel();
 	title.setClass( 'title' );
-	title.setTextContent( 'File' );
+	title.setTextContent( strings.getKey( 'menubar/file' ) );
 	container.add( title );
 
 	var options = new UI.Panel();
@@ -32,7 +33,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'New' );
+	option.setTextContent( strings.getKey( 'menubar/file/new' ) );
 	option.onClick( function () {
 
 		if ( confirm( 'Any unsaved data will be lost. Are you sure?' ) ) {
@@ -67,7 +68,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Import' );
+	option.setTextContent( strings.getKey( 'menubar/file/import' ) );
 	option.onClick( function () {
 
 		fileInput.click();
@@ -83,7 +84,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Export Geometry' );
+	option.setTextContent( strings.getKey( 'menubar/file/export/geometry' ) );
 	option.onClick( function () {
 
 		var object = editor.selected;
@@ -126,7 +127,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Export Object' );
+	option.setTextContent( strings.getKey( 'menubar/file/export/object' ) );
 	option.onClick( function () {
 
 		var object = editor.selected;
@@ -160,7 +161,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Export Scene' );
+	option.setTextContent( strings.getKey( 'menubar/file/export/scene' ) );
 	option.onClick( function () {
 
 		var output = editor.scene.toJSON();
@@ -189,7 +190,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Export DAE' );
+	option.setTextContent( strings.getKey( 'menubar/file/export/dae' ) );
 	option.onClick( function () {
 
 		var exporter = new THREE.ColladaExporter();
@@ -207,7 +208,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Export GLB' );
+	option.setTextContent( strings.getKey( 'menubar/file/export/glb' ) );
 	option.onClick( function () {
 
 		var exporter = new THREE.GLTFExporter();
@@ -227,7 +228,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Export GLTF' );
+	option.setTextContent( strings.getKey( 'menubar/file/export/gltf' ) );
 	option.onClick( function () {
 
 		var exporter = new THREE.GLTFExporter();
@@ -246,7 +247,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Export OBJ' );
+	option.setTextContent( strings.getKey( 'menubar/file/export/obj' ) );
 	option.onClick( function () {
 
 		var object = editor.selected;
@@ -269,7 +270,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Export STL' );
+	option.setTextContent( strings.getKey( 'menubar/file/export/stl' ) );
 	option.onClick( function () {
 
 		var exporter = new THREE.STLExporter();
@@ -287,7 +288,7 @@ Menubar.File = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Publish' );
+	option.setTextContent( strings.getKey( 'menubar/file/publish' ) );
 	option.onClick( function () {
 
 		var zip = new JSZip();

+ 5 - 3
editor/js/Menubar.Help.js

@@ -4,12 +4,14 @@
 
 Menubar.Help = function ( editor ) {
 
+	var strings = editor.strings;
+
 	var container = new UI.Panel();
 	container.setClass( 'menu' );
 
 	var title = new UI.Panel();
 	title.setClass( 'title' );
-	title.setTextContent( 'Help' );
+	title.setTextContent( strings.getKey( 'menubar/help' ) );
 	container.add( title );
 
 	var options = new UI.Panel();
@@ -20,7 +22,7 @@ Menubar.Help = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'Source code' );
+	option.setTextContent( strings.getKey( 'menubar/help/source_code' ) );
 	option.onClick( function () {
 
 		window.open( 'https://github.com/mrdoob/three.js/tree/master/editor', '_blank' )
@@ -32,7 +34,7 @@ Menubar.Help = function ( editor ) {
 
 	var option = new UI.Row();
 	option.setClass( 'option' );
-	option.setTextContent( 'About' );
+	option.setTextContent( strings.getKey( 'menubar/help/about' ) );
 	option.onClick( function () {
 
 		window.open( 'http://threejs.org', '_blank' );

+ 2 - 1
editor/js/Menubar.Play.js

@@ -5,6 +5,7 @@
 Menubar.Play = function ( editor ) {
 
 	var signals = editor.signals;
+	var strings = editor.strings;
 
 	var container = new UI.Panel();
 	container.setClass( 'menu' );
@@ -13,7 +14,7 @@ Menubar.Play = function ( editor ) {
 
 	var title = new UI.Panel();
 	title.setClass( 'title' );
-	title.setTextContent( 'Play' );
+	title.setTextContent( strings.getKey( 'menubar/play' ) );
 	title.onClick( function () {
 
 		if ( isPlaying === false ) {

+ 31 - 1
editor/js/Sidebar.Settings.js

@@ -12,7 +12,37 @@ Sidebar.Settings = function ( editor ) {
 	container.setPaddingTop( '20px' );
 	container.setPaddingBottom( '20px' );
 
-	// class
+	// language
+
+	var options = {
+		'en': 'English',
+		'zh': '中文'
+	};
+
+	var languageRow = new UI.Row();
+	var language = new UI.Select().setWidth( '150px' );
+	language.setOptions( options );
+
+	if ( config.getKey( 'language' ) !== undefined ) {
+
+		language.setValue( config.getKey( 'language' ) );
+
+	}
+
+	language.onChange( function () {
+
+		var value = this.getValue();
+
+		editor.config.setKey( 'language', value );
+
+	} );
+
+	languageRow.add( new UI.Text( 'Language' ).setWidth( '90px' ) );
+	languageRow.add( language );
+
+	container.add( languageRow );
+
+	// theme
 
 	var options = {
 		'css/light.css': 'light',

+ 125 - 0
editor/js/Strings.js

@@ -0,0 +1,125 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+var Strings = function ( config ) {
+
+	var language = config.getKey( 'language' );
+
+	var values = {
+
+		en: {
+			'menubar/file': 'File',
+			'menubar/file/new': 'New',
+			'menubar/file/import': 'Import',
+			'menubar/file/export/geometry': 'Export Geometry',
+			'menubar/file/export/object': 'Export Object',
+			'menubar/file/export/scene': 'Export Scene',
+			'menubar/file/export/dae': 'Export DAE',
+			'menubar/file/export/glb': 'Export GLB',
+			'menubar/file/export/gltf': 'Export GLTF',
+			'menubar/file/export/obj': 'Export OBJ',
+			'menubar/file/export/stl': 'Export STL',
+			// 'menubar/file/export/stl_binary': 'Export STL (Binary)',
+			'menubar/file/publish': 'Publish',
+
+			'menubar/edit': 'Edit',
+			'menubar/edit/undo': 'Undo (Ctrl+Z)',
+			'menubar/edit/redo': 'Redo (Ctrl+Shift+Z)',
+			'menubar/edit/clear_history': 'Clear History',
+			'menubar/edit/clone': 'Clone',
+			'menubar/edit/delete': 'Delete (Del)',
+			'menubar/edit/minify_shaders': 'Minify Shaders',
+
+			'menubar/add': 'Add',
+			'menubar/add/group': 'Group',
+			'menubar/add/plane': 'Plane',
+			'menubar/add/box': 'Box',
+			'menubar/add/circle': 'Circle',
+			'menubar/add/cylinder': 'Cylinder',
+			'menubar/add/sphere': 'Sphere',
+			'menubar/add/icosahedron': 'Icosahedron',
+			'menubar/add/torus': 'Torus',
+			'menubar/add/torusknot': 'TorusKnot',
+			'menubar/add/lathe': 'Lathe',
+			'menubar/add/sprite': 'Sprite',
+			'menubar/add/pointlight': 'PointLight',
+			'menubar/add/spotlight': 'SpotLight',
+			'menubar/add/directionallight': 'DirectionalLight',
+			'menubar/add/hemispherelight': 'HemisphereLight',
+			'menubar/add/ambientlight': 'AmbientLight',
+			'menubar/add/perspectivecamera': 'PerspectiveCamera',
+
+			'menubar/play': 'Play',
+
+			'menubar/examples': 'Examples',
+
+			'menubar/help': 'Help',
+			'menubar/help/source_code': 'Source Code',
+			'menubar/help/about': 'About'
+		},
+
+		zh: {
+			'menubar/file': '文件',
+			'menubar/file/new': '新建',
+			'menubar/file/import': '导入',
+			'menubar/file/export/geometry': '导出几何体',
+			'menubar/file/export/object': '导出物体',
+			'menubar/file/export/scene': '导出场景',
+			'menubar/file/export/dae': '导出DAE',
+			'menubar/file/export/glb': '导出GLB',
+			'menubar/file/export/gltf': '导出GLTF',
+			'menubar/file/export/obj': '导出OBJ',
+			'menubar/file/export/stl': '导出STL',
+			// 'menubar/file/export/stl_binary': '导出STL(二进制)',
+			'menubar/file/publish': '发布',
+
+			'menubar/edit': '编辑',
+			'menubar/edit/undo': '撤销 (Ctrl+Z)',
+			'menubar/edit/redo': '重做 (Ctrl+Shift+Z)',
+			'menubar/edit/clear_history': '清空历史记录',
+			'menubar/edit/clone': '拷贝',
+			'menubar/edit/delete': '删除 (Del)',
+			'menubar/edit/minify_shaders': '压缩着色器',
+
+			'menubar/add': '添加',
+			'menubar/add/group': '组',
+			'menubar/add/plane': '平面',
+			'menubar/add/box': '正方体',
+			'menubar/add/circle': '圆',
+			'menubar/add/cylinder': '圆柱体',
+			'menubar/add/sphere': '球体',
+			'menubar/add/icosahedron': '二十面体',
+			'menubar/add/torus': '圆环体',
+			'menubar/add/torusknot': '环面纽结体',
+			'menubar/add/lathe': '酒杯',
+			'menubar/add/sprite': '精灵',
+			'menubar/add/pointlight': '点光源',
+			'menubar/add/spotlight': 'spotlight',
+			'menubar/add/directionallight': 'directionallight',
+			'menubar/add/hemispherelight': '半球光',
+			'menubar/add/ambientlight': '环境光',
+			'menubar/add/perspectivecamera': '透视相机',
+
+			'menubar/play': '启动',
+
+			'menubar/examples': '示例',
+
+			'menubar/help': '帮助',
+			'menubar/help/source_code': '源码',
+			'menubar/help/about': '关于'
+		}
+
+	};
+
+	return {
+
+		getKey: function ( key ) {
+
+			return values[ language ][ key ] || '???';
+
+		}
+
+	}
+
+};