diff --git a/src/UI/components/Component.js b/src/UI/components/Component.js index 7ae6aa4..ba81237 100644 --- a/src/UI/components/Component.js +++ b/src/UI/components/Component.js @@ -69,8 +69,9 @@ class MCComponent extends HTMLElement { if (!componentName) throw "Component registration failed: Missing componentName."; return customElements.define(componentName, this); }; - static asyncLoadAndDefine() { - return this.asyncLoadTemplateByUrl().then(_ => this.define()); + static async asyncLoadAndDefine() { + const _ = await this.asyncLoadTemplateByUrl(); + return this.define(); }; static getTemplateByUrl(url = this.templateUrl) { return mcComponents[url]; diff --git a/src/UI/doc.txt b/src/UI/doc.txt index c281c53..2b6d32e 100644 --- a/src/UI/doc.txt +++ b/src/UI/doc.txt @@ -1,11 +1,11 @@ +---------+ +---------+ +-----------+ | preload |---------------> welcome <-----> howToPlay | -+---------+ +-^--^--^-+ +-----------+ - | | | - | | +---------------------+ - | +-1------------1-+ | - | | | ++---------+ +^-^-^--^-+ +-----------+ + | | | | + +----------------+ +---+ | | +---------------------+ + | ChangeLanguage <-+ ++ +-1------------1-+ | + +----------------+ | | | +----------------+ +---v---------+ +----v----+ | | createNewWorld <------> selectWorld | | setting | | +----------------+ +-------------+ +----^----+ | diff --git a/src/UI/index.js b/src/UI/index.js index 06e92c5..4742df3 100644 --- a/src/UI/index.js +++ b/src/UI/index.js @@ -9,6 +9,7 @@ export * from "./pages/LoadTerrainPage.js"; export * from "./pages/PausePage.js"; export * from "./pages/PlayPage.js"; export * from "./pages/CreateNewWorldPage.js"; +export * from "./pages/ChangeLanguagePage.js" // mc components export * from "./components/MCButton.js"; diff --git a/src/UI/pages/ChangeLanguagePage.html b/src/UI/pages/ChangeLanguagePage.html new file mode 100644 index 0000000..ef5972c --- /dev/null +++ b/src/UI/pages/ChangeLanguagePage.html @@ -0,0 +1,57 @@ + + +
+

Languages

+ +
+ Exit +
diff --git a/src/UI/pages/ChangeLanguagePage.js b/src/UI/pages/ChangeLanguagePage.js new file mode 100644 index 0000000..5e87a3e --- /dev/null +++ b/src/UI/pages/ChangeLanguagePage.js @@ -0,0 +1,21 @@ + +import { Page } from "./Page.js"; +import "../../i18n.js"; +class ChangeLanguagePage extends Page { + static get outdegree() { return ["welcome", ]; }; + constructor() { + super(); + var table = this.shadowRoot.getElementById('table'); + for (var lang in i18n_module.languages) { + var row = document.createElement('tr'); + row.innerHTML = `${i18n_module['languages'][lang]['name']}`; + table.appendChild(row); + } + } + onHistoryBack() { this.close(); }; +} + +ChangeLanguagePage.asyncLoadAndDefine(); +export { + ChangeLanguagePage, +}; diff --git a/src/UI/pages/CreateNewWorldPage.html b/src/UI/pages/CreateNewWorldPage.html index e0a05da..f34211a 100644 --- a/src/UI/pages/CreateNewWorldPage.html +++ b/src/UI/pages/CreateNewWorldPage.html @@ -20,15 +20,15 @@ }
-

Create New World

- - +

+ +
- World Type: Normal - Trees: On + +
- Create New World - Cancel + +
diff --git a/src/UI/pages/CreateNewWorldPage.js b/src/UI/pages/CreateNewWorldPage.js index f65dd05..4dec15b 100644 --- a/src/UI/pages/CreateNewWorldPage.js +++ b/src/UI/pages/CreateNewWorldPage.js @@ -1,20 +1,30 @@ import { Page, pm } from "./Page.js"; - +import "../../i18n.js"; class CreateNewWorldPage extends Page { static get outdegree() { return ["select-world", "play", ]; }; constructor() { super(); - this.typeBtn = this.shadowRoot.getElementById("world-type-btn"); + for (var key in i18n['ui']) { + var node = this.shadowRoot.getElementById(key); + if (node) { node.innerText = i18n['ui'][key]; node.setAttribute('placeholder', i18n['ui'][key]); } + } + this.typeBtn = this.shadowRoot.getElementById("world-type-btn-event"); this.typeEcho = this.shadowRoot.getElementById("world-type-echo"); - this.createBtn = this.shadowRoot.getElementById("create-new-word"); + this.typeEcho.setAttribute("data", "normal"); + this.createBtn = this.shadowRoot.getElementById("create-new-world"); this.worldName = this.shadowRoot.getElementById("world-name"); this.worldSeed = this.shadowRoot.getElementById("world-seed"); this.typeBtn.addEventListener("click", () => { - if (this.typeEcho.innerHTML == "Normal") - this.typeEcho.innerHTML = "Flat"; - else this.typeEcho.innerHTML = "Normal"; + if (this.typeEcho.innerHTML == i18n['ui']['normal']) { + this.typeEcho.innerHTML = i18n['ui']['flat']; + this.typeEcho.setAttribute("data", "flat"); + } + else { + this.typeEcho.innerHTML = i18n['ui']['normal']; + this.typeEcho.setAttribute("data", "normal"); + } }); this.createBtn.addEventListener("click", () => { @@ -25,7 +35,7 @@ class CreateNewWorldPage extends Page { worldType: ({ Normal: "pre-classic", Flat: "flat", - })[this.typeEcho.innerHTML], + })[this.typeEcho.getAttribute("data")], seed, }); }); diff --git a/src/UI/pages/HowToPlayPage.html b/src/UI/pages/HowToPlayPage.html index e69d28e..150923f 100644 --- a/src/UI/pages/HowToPlayPage.html +++ b/src/UI/pages/HowToPlayPage.html @@ -50,15 +50,15 @@ }
-

How to play

+

- - - - - - - + + + + + + +
WASD Move; Double-click W to Sprint
Spacebar Jump; Double-click to switch Fly Mode
Shift/X When Fly Mode is on, causes the player to lose altitude (descend)
ESC Gives back cursor control
E Open inventory
Left/Right button Destroy/Place blocks
Scroll Scrolls through the Hotbar
- Back +
diff --git a/src/UI/pages/HowToPlayPage.js b/src/UI/pages/HowToPlayPage.js index 2a32b9b..1b0d14a 100644 --- a/src/UI/pages/HowToPlayPage.js +++ b/src/UI/pages/HowToPlayPage.js @@ -1,14 +1,19 @@ import { Page } from "./Page.js"; - +import "../../i18n.js"; class HowToPlayPage extends Page { static get outdegree() { return ["welcome", ]; }; + constructor() { + super(); + for (var key in i18n['how-to-play']) { + var node = this.shadowRoot.getElementById(key); + if (node) { node.innerHTML = i18n['how-to-play'][key]; } + } + } onHistoryBack() { this.close(); }; } HowToPlayPage.asyncLoadAndDefine(); - - export { HowToPlayPage, }; diff --git a/src/UI/pages/LoadTerrainPage.js b/src/UI/pages/LoadTerrainPage.js index 7f8d0d9..ab5072e 100644 --- a/src/UI/pages/LoadTerrainPage.js +++ b/src/UI/pages/LoadTerrainPage.js @@ -1,6 +1,6 @@ import { Page, pm } from "./Page.js"; - +import "../../i18n.js"; import { World } from "../../World/World.js"; import { WorldRenderer } from "../../Renderer/WorldRenderer.js"; diff --git a/src/UI/pages/Page.js b/src/UI/pages/Page.js index d8c70a4..e944cf7 100644 --- a/src/UI/pages/Page.js +++ b/src/UI/pages/Page.js @@ -88,6 +88,10 @@ class Page extends MCComponent { get outdegree() { return this.constructor.outdegree; }; constructor() { super(); + for (var key in i18n['ui']) { + var node = this.shadowRoot.getElementById(key); + if (node) { node.innerText = i18n['ui'][key]; } + } if (new.target.name === "Page") throw "Class 'Page' cannot be instantiated!"; pageManager.addTransitions(this.outdegree.map(to => ({ diff --git a/src/UI/pages/PausePage.html b/src/UI/pages/PausePage.html index a07f4ac..0851f2a 100644 --- a/src/UI/pages/PausePage.html +++ b/src/UI/pages/PausePage.html @@ -21,7 +21,7 @@ }
- Resume Game - Settings - Quit + + +
diff --git a/src/UI/pages/PausePage.js b/src/UI/pages/PausePage.js index 82aa541..4cad551 100644 --- a/src/UI/pages/PausePage.js +++ b/src/UI/pages/PausePage.js @@ -1,5 +1,6 @@ import { Page } from "./Page.js"; +import "../../i18n.js"; class PausePage extends Page { static get outdegree() { return ["play", "welcome", "setting", ]; }; @@ -11,6 +12,14 @@ class PausePage extends Page { PausePage.asyncLoadAndDefine(); +for (var key in i18n['ui']) { + try { + document.getElementById(key).innerText = i18n['ui'][key]; + } + catch (e) { + // console.log(e); + } +} export { PausePage, diff --git a/src/UI/pages/PlayPage.html b/src/UI/pages/PlayPage.html index f994964..7feeb9e 100644 --- a/src/UI/pages/PlayPage.html +++ b/src/UI/pages/PlayPage.html @@ -15,7 +15,7 @@ pointer-events: none; } -Your browser does not support canvas. Please upgrade your browser. + diff --git a/src/UI/pages/PlayPage.js b/src/UI/pages/PlayPage.js index 6ef74af..b8d84f1 100644 --- a/src/UI/pages/PlayPage.js +++ b/src/UI/pages/PlayPage.js @@ -1,6 +1,7 @@ import { Page, pm } from "./Page.js"; import { PlayerLocalController } from "../../Entity/PlayerLocalController.js"; +import "../../i18n.js"; class PlayPage extends Page { static get outdegree() { return ["load-terrain", "pause", ]; }; @@ -95,6 +96,15 @@ pm.addEventListener("pause=>play", (pause, play) => { PlayPage.asyncLoadAndDefine(); +for (var key in i18n['ui']) { + try { + document.getElementById(key).innerText = i18n['ui'][key]; + } + catch (e) { + // console.log(e); + } +} + export { PlayPage, diff --git a/src/UI/pages/SelectWorldPage.html b/src/UI/pages/SelectWorldPage.html index 4e2238c..b2ef140 100644 --- a/src/UI/pages/SelectWorldPage.html +++ b/src/UI/pages/SelectWorldPage.html @@ -69,7 +69,7 @@ }
-

Select World

+

- Play Selected World - Delete - Create New World - Cancel + + + +
diff --git a/src/UI/pages/SelectWorldPage.js b/src/UI/pages/SelectWorldPage.js index 2d840a0..6905fea 100644 --- a/src/UI/pages/SelectWorldPage.js +++ b/src/UI/pages/SelectWorldPage.js @@ -1,5 +1,6 @@ import { Page, pm } from "./Page.js"; +import "../../i18n.js"; class SelectWorldPage extends Page { static get outdegree() { return ["welcome", "play", "create-new-world", ]; }; @@ -24,7 +25,7 @@ class SelectWorldPage extends Page {
  • ${world.name} Created - ${timestamp2str(world.createAt)} - Modified - ${timestamp2str(world.modifyAt)} + Saved - ${timestamp2str(world.modifyAt)} ${world.type} ${storageId}
  • @@ -58,6 +59,15 @@ class SelectWorldPage extends Page { SelectWorldPage.asyncLoadAndDefine(); +for (var key in i18n['ui']) { + try { + document.getElementById(key).innerText = i18n['ui'][key]; + } + catch (e) { + // console.log(e); + } +} + export { SelectWorldPage, }; diff --git a/src/UI/pages/SettingPage.html b/src/UI/pages/SettingPage.html index dc68cff..bbe52ce 100644 --- a/src/UI/pages/SettingPage.html +++ b/src/UI/pages/SettingPage.html @@ -27,19 +27,19 @@ }
    -

    Options

    +

    - default + default
    - default + default
    - default + default
    - Face-dependent Lighting: OFF + OFF
    - Debug output: OFF + OFF
    - Back +
    diff --git a/src/UI/pages/SettingPage.js b/src/UI/pages/SettingPage.js index ab4d9fc..40ee837 100644 --- a/src/UI/pages/SettingPage.js +++ b/src/UI/pages/SettingPage.js @@ -1,6 +1,7 @@ import { Page, pm } from "./Page.js"; import { settings } from "../../settings.js"; +import "../../i18n.js"; class SettingPage extends Page { static get outdegree() { return ["welcome", "pause", ]; }; @@ -94,6 +95,15 @@ class SettingPage extends Page { SettingPage.asyncLoadAndDefine(); +for (var key in i18n['ui']) { + try { + document.querySelector("body > mcpage-setting").shadowRoot.getElementById(key).label = i18n['ui'][key]; + document.getElementById(key).innerText = i18n['ui'][key]; + } + catch (e) { + // console.log(e); + } +} export { SettingPage, diff --git a/src/UI/pages/WelcomePage.html b/src/UI/pages/WelcomePage.html index f1deeba..647765a 100644 --- a/src/UI/pages/WelcomePage.html +++ b/src/UI/pages/WelcomePage.html @@ -55,7 +55,8 @@

    View in GitHub!

    diff --git a/src/UI/pages/WelcomePage.js b/src/UI/pages/WelcomePage.js index 38d0fbc..feff63f 100644 --- a/src/UI/pages/WelcomePage.js +++ b/src/UI/pages/WelcomePage.js @@ -1,13 +1,17 @@ import { Page } from "./Page.js"; import { settings } from "../../settings.js"; - +import "../../i18n.js"; import { WelcomeRenderer } from "../../Renderer/WelcomePageRenderer.js"; class WelcomePage extends Page { - static get outdegree() { return ["select-world", "how-to-play", "setting", ]; }; + static get outdegree() { return ["select-world", "how-to-play", "setting", "change-language",]; }; constructor() { super(); + for (var key in i18n['ui']) { + var node = this.shadowRoot.getElementById(key); + if (node) { node.innerText = i18n['ui'][key]; } + } this.bgCanvas = this.shadowRoot.getElementById("background-canvas"); this.renderer = null; }; diff --git a/src/World/Block.js b/src/World/Block.js index 1e0eaa2..5d34e62 100644 --- a/src/World/Block.js +++ b/src/World/Block.js @@ -1,5 +1,6 @@ import { asyncLoadResByUrl } from "../utils/loadResources.js"; import { textureMipmapByTile, prepareTextureAarray, blockInventoryTexture } from "../processingPictures.js"; +import "../i18n.js"; // 用32位储存方块id和data。高16位存data,低16位存id。 @@ -44,7 +45,7 @@ class Block { friction = 1, id = findEmptyIdSlot(), bd = 0, - showName = blockName.toLowerCase().replace(/_/g, " ").replace(/^\w|\s\w/g, w => w.toUpperCase()), + showName = i18n['blockShowNames'][blockName], isLeaves = blockName.endsWith("leaves"), isGlass = blockName.endsWith("glass"), isFluid = renderType == Block.renderType.FLUID, diff --git a/src/i18n.js b/src/i18n.js new file mode 100644 index 0000000..c7ebdf3 --- /dev/null +++ b/src/i18n.js @@ -0,0 +1,197 @@ +window.i18n_module = new Object(); +i18n_module.languages = { + 'zh_cn': { + "name": "简体中文", + "blockShowNames": { + "air": "空气", + "stone": "石头", + "granite": "花岗岩", + "polished_granite": "磨制花岗岩", + "diorite": "闪长岩", + "polished_diorite": "磨制闪长岩", + "andesite": "安山岩", + "polished_andesite": "磨制安山岩", + "grass": "草方块", + "dirt": "泥土", + "cobblestone": "原石", + "oak_wood_planks": "橡木木板", + "spruce_wood_planks": "云杉木板", + "birch_wood_planks": "白桦木板", + "jungle_wood_planks": "丛林木板", + "acacia_wood_planks": "金合欢木板", + "dark_oak_wood_planks": "深色橡木木板", + "oak_sapling": "橡树树苗", + "spruce_sapling": "云杉树苗", + "birch_sapling": "白桦树苗", + "jungle_sapling": "丛林树苗", + "acacia_sapling": "金合欢树苗", + "dark_oak_sapling": "深色橡树树苗", + "bedrock": "基岩", + "water": "水", + "flowing_water": "流动的水", + "lava": "熔岩", + "flowing_lava": "流动的熔岩", + "oak_log": "橡木", + "spruce_log": "云杉木", + "birch_log": "白桦木", + "jungle_log": "丛林木", + "oak_leaves": "橡树树叶", + "spruce_leaves": "云杉树叶", + "birch_leaves": "白桦树叶", + "jungle_leaves": "丛林树叶", + "glass": "玻璃", + "acacia_leaves": "金合欢树叶", + "dark_oak_leaves": "深色橡树树叶", + "dandelion": "蒲公英", + "poppy": "虞美人", + "blue_orchid": "兰花", + "allium": "绒球葱", + "azure_bluet": "蓝花美耳草", + "red_tulip": "红色郁金香", + "orange_tulip": "橙色郁金香", + "white_tulip": "白色郁金香", + "pink_tulip": "粉红色郁金香", + "oxeye_daisy": "滨菊", + "crafting_table": "工作台", + "cactus": "仙人掌", + "glowstone": "萤石" + }, + "ui": { + "select-world": "开始", + "how-to-play": "帮助", + "setting": "设置", + "fov": "视野:", + "mouse-sensitivity": "鼠标灵敏度:", + "homepage-blur": "主页模糊度:", + "shade-btn": "禁用平滑光照:", + "debug-output-btn": "调试输出:", + "return": "返回", + "choose-world-title": "选择世界", + "btn-select": "进入选中的世界", + "create-new-world": "创建新世界", + "world-name": "世界名,默认为:'My World'", + "world-seed": "世界种子,留空则随机", + "btn-del": "删除", + "cancel": "取消", + "mainCanvas": "你的浏览器不支持canvas, 请更新浏览器。", + "exit": "退出", + "normal": "普通", + "flat": "超平坦", + "world-type-echo": "普通", + "world-type-btn": "世界类型:", + "tree": "生成树:", + "tree-echo": "打开", + }, + 'how-to-play': { + "title": "帮助", + "wasd": "WASD 移动;双击W疾跑", + "space": "空格 跳跃;双击空格起飞", + "shift": "Shift/X 在飞行模式中降低高度", + "escape": "ESC 进入菜单", + "e": "E 打开物品栏", + "click": "左键/右键 破坏/放置方块", + "roll": "滚轮 切换快捷栏槽位" + } + }, + 'en_us': { + "name": "English", + 'blockShowNames': { + "air": "Air", + "stone": "Stone", + "granite": "Granite", + "polished_granite": "Polished Granite", + "diorite": "Diorite", + "polished_diorite": "Polished Diorite", + "andesite": "Andesite", + "polished_andesite": "Polished Andesite", + "grass": "Grass Block", + "dirt": "Dirt", + "cobblestone": "Cobblestone", + "oak_wood_planks": "Oak Wood Planks", + "spruce_wood_planks": "Spruce Wood Planks", + "birch_wood_planks": "Birch Wood Planks", + "jungle_wood_planks": "Jungle Wood Planks", + "acacia_wood_planks": "Acacia Wood Planks", + "dark_oak_wood_planks": "Dark Oak Wood Planks", + "oak_sapling": "Oak Sapling", + "spruce_sapling": "Spruce Sapling", + "birch_sapling": "Birch Sapling", + "jungle_sapling": "Jungle Sapling", + "acacia_sapling": "Acacia Sapling", + "dark_oak_sapling": "Dark Oak Sapling", + "bedrock": "Bedrock", + "water": "Water", + "flowing_water": "Flowing Water", + "lava": "Lava", + "flowing_lava": "Flowing Lava", + "oak_log": "Oak Log", + "spruce_log": "Spruce Log", + "birch_log": "Birch Log", + "jungle_log": "Jungle Log", + "oak_leaves": "Oak Leaves", + "spruce_leaves": "Spruce Leaves", + "birch_leaves": "Birch Leaves", + "jungle_leaves": "Jungle Leaves", + "glass": "Glass", + "acacia_leaves": "Acacia Leaves", + "dark_oak_leaves": "Dark Oak Leaves", + "dandelion": "Dandelion", + "poppy": "Poppy", + "blue_orchid": "Blue Orchid", + "allium": "Allium", + "azure_bluet": "Azure Bluet", + "red_tulip": "Red Tulip", + "orange_tulip": "Orange Tulip", + "white_tulip": "White Tulip", + "pink_tulip": "Pink Tulip", + "oxeye_daisy": "Oxeye Daisy", + "crafting_table": "Crafting Table", + "cactus": "Cactus", + "glowstone": "Glowstone" + }, + 'ui': { + "select-world": "Start", + "how-to-play": "Help", + "setting": "Settings", + "fov": "FOV: ", + "mouse-sensitivity": "Mouse Sensitivity: ", + "homepage-blur": "Homepage Blur: ", + "shade-btn": "Disable Smooth Lighting: ", + "debug-output-btn": "Debug Output: ", + "return": "Return", + "choose-world-title": "Choose World", + "btn-select": "Play Selected World", + "create-new-world": "Create a New World", + "world-name": "World Name, default to: 'My World'", + "world-seed": "World Seed, leave blank for random", + "btn-del": "Delete", + "cancel": "Cancel", + "mainCanvas": "Your browser doesn't support canvas, please upgrade your browser.", + "exit": "Exit", + "normal": "Normal", + "flat": "Flat", + "world-type-echo": "Normal", + "world-type-btn": "World Type: ", + "tree": "Generate Tree: ", + "tree-echo": "Opened", + }, + 'how-to-play': { + "title": "Help", + "wasd": "WASD Move; Double Click W to Sprint.", + "space": "Space Jump; Double Click to Fly.", + "shift": "Shift/X Lowering Height in Fly.", + "escape": "ESC Open Menu.", + "e": "E Open Inventory", + "click": "Left Click / Right Click Destroy / Build", + "roll": "Roller Change Inventory Slot." + } + } +} +if (localStorage.getItem("language") === null) { + localStorage.setItem('language', 'zh_cn'); +} +window.i18n = i18n_module['languages'][localStorage.getItem('language')]; +i18n_module.set_language = (language_code) => { + window.language_code = language_code; + localStorage.setItem('language', language_code); +} \ No newline at end of file diff --git a/src/main.js b/src/main.js index e700e26..2cb0a57 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,6 @@ import "./globalVeriable.js"; - +import "./i18n.js"; window.addEventListener("contextmenu", e => { if (e.cancelable) e.preventDefault(); }, true); const updatePixelRatio = () => { @@ -39,5 +39,6 @@ localStorage: { modityAt: 最后一次修改世界时的时间戳, }, ... }, + language: 语言(用于i18n) } */ diff --git a/texture/mc-font.ttf b/texture/mc-font.ttf index 55c5075..e67a65e 100644 Binary files a/texture/mc-font.ttf and b/texture/mc-font.ttf differ