diff --git a/locales/ja.json5 b/locales/ja.json5 index ebb1a33..a990f49 100644 --- a/locales/ja.json5 +++ b/locales/ja.json5 @@ -529,7 +529,7 @@ "You will keep your achievements, building levels and sugar lumps.": "実績と施設レベル、角砂糖は引き継がれます。", "Ascending": "昇天中", "So long, cookies.": "クッキーたち、またね。", - "You forfeit your %1.": "貯蓄していた %1クッキー を失いました。", + "You forfeit your %1.": "貯蓄していた %1 を失いました。", "Prestige level:": "名声レベル :", "Heavenly chips:": "ヘブンリーチップス :", "%1 prestige level": [ @@ -3558,7 +3558,7 @@ "Cryogenically preserve your garden.
Plants no longer grow, spread or die; they provide no benefits.
Soil cannot be changed.
Using this will effectively pause your garden.": "菜園を極低温で状態維持する。
全作物の成長が止まり、拡散や枯死も起こらず、効果も発揮しない。
土壌変更も出来ない。
使用することで菜園を効果的に保存することが出来る。", "Garden is frozen. Unfreeze to resume.": "菜園を冷凍しています。解凍するには再度押してください。", "Sacrifice garden": "生贄の畑", - "A swarm of sugar hornets comes down on your garden, destroying every plant as well as every seed you've unlocked - leaving only a %1 seed.
In exchange, they will grant you %2.
This action is only available with a complete seed log.": "砂糖蜂の群れが菜園にやって来る、開放したほぼすべての種が破壊される - %1のみ残る。
引き換えに、 %2 が与えられる。
この動作は品種記録が完成しているときにのみ利用可能。", + "A swarm of sugar hornets comes down on your garden, destroying every plant as well as every seed you've unlocked - leaving only a %1 seed.
In exchange, they will grant you %2.
This action is only available with a complete seed log.": "砂糖蜂の群れが菜園にやって来て、開放したほぼすべての種が破壊される - %1のみ残る。
引き換えに、 %2 が与えられる。
この動作は品種記録が完成しているときにのみ利用可能。", "Do you REALLY want to sacrifice your garden to the sugar hornets?
You will be left with an empty plot and only the %1 seed unlocked.
In return, you will gain %2 sugar lumps.
": "あなたは 本 当 に 砂糖蜂に庭園を捧げたいのですか?
まっさらになった庭園と%1の種子だけが解除された状態となります。
その対価として、 %2角砂糖 を手に入れます。", "Sacrifice!": "生贄に!", "You've sacrificed your garden to the sugar hornets, destroying your crops and your knowledge of seeds.
In the remains, you find %1 sugar lumps.": "菜園を砂糖蜂の生贄にし、作物と種に関する知識を破壊されました。
残骸の中に、 %1角砂糖 見つけました。", @@ -3788,7 +3788,7 @@ "#CATEGORY: フレーバーテキスト/在庫市場": "「在庫市場」のフレーバーテキスト", - "Buy that vintage car you've always wanted. Just pay us back.": "いつも欲しがってたヴィンテージの車を購入しよう。とにかく金を返してもらうんだ。", + "Buy that vintage car you've always wanted. Just pay us back.": "いつも欲しがってたヴィンテージの車を購入しよう。返済はしっかりとしろ。", "Bad credit? No problem. It's your money, and you need it now.": "良くない信用取引だって?問題ない。それは元々あなたの金であり、今あなたが求めるものだ。", "Finance your next house, boat, spouse, etc. You've earned it.": "次の家やボート、配偶者、その他もろもろを融通してもらえ。それらはあなたが稼いできたものだ。", @@ -3849,9 +3849,9 @@ "#CATEGORY: ミニゲーム/神殿/UI": "ミニゲーム「神殿」のUI部分の翻訳", "Pantheon": "神殿", - "Diamond slot": "ダイアモンド", - "Ruby slot": "ルビー", - "Jade slot": "翡翠", + "Diamond slot": "ダイアモンドのスロット", + "Ruby slot": "ルビーのスロット", + "Jade slot": "翡翠のスロット", "empty": "空き", "Release to assign %1 to this slot.": "このスロットに %1 を配置するには、ドロップしてください。", "Drag a spirit onto this slot to assign it.": "聖霊を配置するには、聖霊をこのスロットの上にドラッグしてください。", @@ -5638,5 +5638,7 @@ "check out our %1 with rad cookie shirts, hoodies and stickers": "イカすクッキーシャツやパーカー、ステッカーがある%1をチェック", "Shop": "ショップ", "disable your adblocker (if you want!)": "アドブロッカーの無効化(お任せするよ!)", - "refill": "回復" + "refill": "回復", + "Reincarnated": "転生しました", + "DOUGH JONES INDEX": "ドウ平均株価" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 520a20a..e2f5df4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "better-japanese", - "version": "1.4.7", + "version": "1.4.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "better-japanese", - "version": "1.4.7", + "version": "1.4.8", "license": "ISC", "devDependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index 038735f..e03c0c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "better-japanese", - "version": "1.4.7", + "version": "1.4.8", "description": "", "main": "index.js", "scripts": { diff --git a/src/common/main.js b/src/common/main.js index 40c8420..ee58f60 100644 --- a/src/common/main.js +++ b/src/common/main.js @@ -1,5 +1,15 @@ const betterJapanese = { name: 'betterJapanese', + version: null, + config: { + hash: '0', + replaceJP: true, + replaceNews: true, + numberJP: true, + shortFormatJP: false, + secondFormatJP: true, + ignoreList: [] + }, api: { url: { release: 'https://pages.yukineko.me/better-japanese/api/release.json', @@ -11,15 +21,6 @@ const betterJapanese = { }, cache: null }, - config: { - hash: '0', - replaceJP: true, - replaceNews: true, - numberJP: true, - shortFormatJP: false, - secondFormatJP: true, - ignoreList: [] - }, isDev: false, initialized: false, fallbackTimer: 0, @@ -35,6 +36,11 @@ const betterJapanese = { isRegisteredHook: false, init: function() { + let versionPath = App ? `file:///${App.mods['BetterJapanese'].dir.replace(/\\/g, '/')}/version.json` : 'https://pages.yukineko.me/better-japanese/version.json' + this.getJSON(versionPath).then(res => { + res ? this.version = res.version : this.version = '0.0.0' + }) + this.fallbackTimer = setTimeout(() => { this.checkUpdate() this.initialized = true @@ -45,7 +51,7 @@ const betterJapanese = { if (!this.isRegisteredHook) this.initAfterLoad() // Web版で既にDOMが構築されていた場合はDOMを再構成するスクリプトを読み込む (一部の翻訳が適用されないため) - if (!App && Game.ready) Game.LoadMod('https://pages.yukineko.me/better-japanese/rebuild.js') + if (!App && Game.ready) Game.LoadMod(`https://pages.yukineko.me/better-japanese/rebuild.js?nocache=${Date.now()}`) this.log('Initialized') }, @@ -55,7 +61,7 @@ const betterJapanese = { // メニューに独自ボタンを実装 // この方法で実装しないとCCSEなどのメニュー独自実装Modと競合してしまう - let origin = eval('Game.UpdateMenu.toString()').split('\n') + let origin = Game.UpdateMenu.toString().split('\n') origin.splice(origin.length - 1, 0, ` if (Game.onMenu == 'prefs') { betterJapanese.injectMenu() @@ -63,12 +69,13 @@ const betterJapanese = { if (Game.onMenu == 'stats') { betterJapanese.fixStats() + betterJapanese.injectStats() } `) - eval(`Game.UpdateMenu = ${origin.join('\n')}`) + Function(`Game.UpdateMenu = ${origin.join('\n')}`)() // 時間表記からカンマを取り除く - betterJapanese.origins.sayTime = Game.sayTime + if (!betterJapanese.origins.sayTime) betterJapanese.origins.sayTime = Game.sayTime Game.sayTime = function(time, detail) { return betterJapanese.origins.sayTime(time, detail).replaceAll(', ', '') } @@ -95,7 +102,7 @@ const betterJapanese = { ] // 設定によって日本語単位を使用するように変更、同時にカンマ区切りも場合によって変更 - betterJapanese.origins.beautify = Beautify + if (!betterJapanese.origins.beautify) betterJapanese.origins.beautify = Beautify Beautify = function(val, floats) { let negative = (val < 0) let decimal = '' @@ -115,6 +122,15 @@ const betterJapanese = { return negative ? '-' + output : output + decimal } + // 指数表記の場合表示が崩れる現象を修正 + if (!betterJapanese.origins.simpleBeautify) betterJapanese.origins.simpleBeautify = SimpleBeautify + SimpleBeautify = function(val) { + if (val.toString().indexOf('e+') >= 0) { + return val.toString().replace(/(?<=.)(\d{3})(?=\d)/g, '$1,') + } + return betterJapanese.origins.simpleBeautify(val) + } + // カスタムCSSを適用 let customStyle = document.createElement('style') customStyle.innerHTML = ` @@ -194,9 +210,7 @@ const betterJapanese = { // 在庫市場のquoteを実装 while (!Game.Objects['Bank'].hasOwnProperty('minigame')) await new Promise(resolve => setTimeout(resolve, 1000)) - if (typeof (betterJapanese.origins.goodTooltip) === 'undefined') { - betterJapanese.origins.goodTooltip = Game.Objects['Bank'].minigame.goodTooltip - } + if (!betterJapanese.origins.goodTooltip) betterJapanese.origins.goodTooltip = Game.Objects['Bank'].minigame.goodTooltip Game.Objects['Bank'].minigame.goodTooltip = function(id) { return function() { let desc = betterJapanese.origins.goodTooltip(id)() @@ -206,8 +220,13 @@ const betterJapanese = { } } + // 菜園情報の画像を差し替え + while (!Game.Objects['Farm'].hasOwnProperty('minigame')) await new Promise(resolve => setTimeout(resolve, 1000)) + if (!betterJapanese.origins.toolInfoDescFunc) betterJapanese.origins.toolInfoDescFunc = Game.Objects['Farm'].minigame.tools['info'].descFunc + Function('Game.Objects[\'Farm\'].minigame.tools[\'info\'].descFunc=' + Game.Objects['Farm'].minigame.tools['info'].descFunc.toString().replace('img/gardenTip.png', 'https://pages.yukineko.me/better-japanese/assets/gardenTip.png'))() + // 情報欄の翻訳 - betterJapanese.origins.updateLog = Game.updateLog + if (!betterJapanese.origins.updateLog) betterJapanese.origins.updateLog = Game.updateLog Game.updateLog = `
${loc('Info')}
@@ -280,7 +299,7 @@ const betterJapanese = { // 巡り続ける読本のフレーバーテキスト翻訳、thisを使うので非ラムダ式(以降同様) let upgrade = Game.Upgrades['Endless book of prose'] upgrade.desc = loc('%1 are twice as efficient.', cap(upgrade.buildingTie1.plural)) - upgrade.originDescFunc = upgrade.descFunc + if(!upgrade.originDescFunc) upgrade.originDescFunc = upgrade.descFunc upgrade.descFunc = function() { let str = loc(FindLocStringByPart(`Upgrade quote ${this.id}`), Game.bakeryName) let n = 26 @@ -346,7 +365,7 @@ const betterJapanese = { Game.Upgrades['Golden switch [on]'].descFunc = func // 猫の場合「購入済み」タグが変化することを翻訳にも反映 - betterJapanese.origins.crateTooltip = Game.crateTooltip + if (!betterJapanese.origins.crateTooltip) betterJapanese.origins.crateTooltip = Game.crateTooltip Game.crateTooltip = function(me, context) { let tooltipText = betterJapanese.origins.crateTooltip(me, context) if (Game.sesame) { @@ -355,16 +374,13 @@ const betterJapanese = { if (me.type == 'upgrade' && me.bought > 0 && me.pool != 'tech' && me.kitten) { return tooltipText.replace(`
${loc('Purchased')}
`, `
${loc('[Tag]Purrchased')}
`) } - return tooltipText } // 英語以外でも施設固有の生産方法をツールチップに表示 for (let i in Game.Objects) { let obj = Game.Objects[i] - if (typeof (betterJapanese.origins.tooltip) === 'undefined') { - betterJapanese.origins.tooltip = obj.tooltip - } + if (!betterJapanese.origins.tooltip) betterJapanese.origins.tooltip = obj.tooltip obj.actionNameJP = loc(obj.actionName) obj.tooltip = function() { const strDivDescriptionBlock = '
' @@ -381,9 +397,7 @@ const betterJapanese = { // 英語以外でも施設固有の角砂糖によるレベルアップの恩恵を表示 for (let i in Game.Objects) { let obj = Game.Objects[i] - if (typeof (betterJapanese.origins.levelTooltip) === 'undefined') { - betterJapanese.origins.levelTooltip = obj.levelTooltip - } + if (betterJapanese.origins.levelTooltip) betterJapanese.origins.levelTooltip = obj.levelTooltip obj.levelTooltip = function() { const strDivLine = '
' let defaultTooltip = betterJapanese.origins.levelTooltip.bind(this)().split(strDivLine) @@ -392,7 +406,7 @@ const betterJapanese = { } } - betterJapanese.origins.parseLoc = parseLoc + if (!betterJapanese.origins.parseLoc) betterJapanese.origins.parseLoc = parseLoc parseLoc = function(str, params) { // 独自実装されている翻訳でコケないように修正 if (str.constructor === Object) return '' @@ -406,11 +420,11 @@ const betterJapanese = { // ニュース欄の改善を有効化していれば置き換え if (betterJapanese.config.replaceNews) { // ニュースのフォーチュンクッキーの表示が壊れる問題を修正 - let tickerOrigin = eval('Game.getNewTicker.toString()').replace('me.name.indexOf(\'#\')', 'me.dname.indexOf(\'No.\')').replace(/me\.baseDesc/g, 'me.ddesc') - eval(`Game.getNewTicker = ${tickerOrigin}`) + let tickerOrigin = Game.getNewTicker.toString().replace('me.name.indexOf(\'#\')', 'me.dname.indexOf(\'No.\')').replace(/me\.baseDesc/g, 'me.ddesc') + Function(`Game.getNewTicker = ${tickerOrigin}`)() // ニュースを英語で出力させるように - betterJapanese.origins.getNewTicker = Game.getNewTicker + if (!betterJapanese.origins.getNewTicker) betterJapanese.origins.getNewTicker = Game.getNewTicker Game.getNewTicker = function(manual) { let isDefaultEN = EN EN = true @@ -419,7 +433,7 @@ const betterJapanese = { } // ニュースの文章を翻訳 - betterJapanese.origins.tickerDraw = Game.TickerDraw + if (!betterJapanese.origins.tickerDraw) betterJapanese.origins.tickerDraw = Game.TickerDraw Game.TickerDraw = function() { Game.Ticker = betterJapanese.locTicker(Game.Ticker) betterJapanese.origins.tickerDraw() @@ -427,13 +441,17 @@ const betterJapanese = { } // ミニゲームでの砂糖使用時に表示する確認ツールチップを翻訳 - betterJapanese.origins.refillLump = Game.refillLump - eval('Game.refillLump=' + Game.refillLump.toString().replace('\'refill\'', 'loc(\'refill\')')) + if (!betterJapanese.origins.refillLump) betterJapanese.origins.refillLump = Game.refillLump + Function('Game.refillLump = ' + Game.refillLump.toString().replace('\'refill\'', 'loc(\'refill\')'))() // イースターのエッグ解放時に表示するツールチップのアップグレード名を翻訳 - betterJapanese.origins.dropEgg = Game.DropEgg - eval('Game.DropEgg=' + Game.DropEgg.toString().replace(/(Game\.Notify\(loc\("You found an egg\!"\),'\'\+)drop(\+'\<\/b\>',Game\.Upgrades\[drop\]\.icon\);)/, '$1Game.Upgrades[drop].dname$2')) + if (!betterJapanese.origins.dropEgg) betterJapanese.origins.dropEgg = Game.DropEgg + Function('Game.DropEgg = ' + Game.DropEgg.toString().replace(/(Game\.Notify\(loc\("You found an egg\!"\),'\'\+)drop(\+'\<\/b\>',Game\.Upgrades\[drop\]\.icon\);)/, '$1Game.Upgrades[drop].dname$2'))() + // 転生後に表示されるツールチップを翻訳 + if (!betterJapanese.origins.reincarnate) betterJapanese.origins.reincarnate = Game.Reincarnate + Function('Game.Reincarnate = ' + Game.Reincarnate.toString().replace(/(Game\.Notify\()'Reincarnated'(,loc\("Hello, cookies!"\),\[10,0\],4\);)/, '$1loc("Reincarnated")$2'))() + // hookを削除 Game.removeHook('create', betterJapanese.initAfterLoad) }, @@ -478,6 +496,15 @@ const betterJapanese = { this.writeButton('toggleSecondFormatJPButton', 'secondFormatJP', '第二単位', `${loc('ON')}の場合はXXXX億YYYY万、${loc('OFF')}の場合はXXXX.YYYY億のように表示されます。`, updateAll) }, + injectStats: function() { + let target = l('statsGeneral') + let div = document.createElement('div') + div.innerHTML = `日本語訳改善Mod: ${betterJapanese.version}` + div.className = 'listing' + + if (target) target.parentNode.appendChild(div) + }, + fixStats: function() { const strLegacyStarted = '
' + loc('Legacy started:') + '' l('menu').innerHTML = l('menu').innerHTML.replace(new RegExp(strLegacyStarted + ' (.+?), (.+?)
'), strLegacyStarted + ' $1、$2
') diff --git a/src/web/assets/gardenTip.png b/src/web/assets/gardenTip.png new file mode 100644 index 0000000..2bbf1ff Binary files /dev/null and b/src/web/assets/gardenTip.png differ diff --git a/src/web/mod.js b/src/web/mod.js index 00ebe37..572767b 100644 --- a/src/web/mod.js +++ b/src/web/mod.js @@ -7,4 +7,4 @@ if (language && conf.replaceJP) { ModLanguage('JA', JSON.parse(language)) } -Game.LoadMod(`https://pages.yukineko.me/better-japanese/assets/main.js?v=${Game.version}`) \ No newline at end of file +Game.LoadMod(`https://pages.yukineko.me/better-japanese/assets/main.js?nocache=${Date.now()}`) \ No newline at end of file diff --git a/src/web/rebuild.js b/src/web/rebuild.js index a944358..a7cf8fb 100644 --- a/src/web/rebuild.js +++ b/src/web/rebuild.js @@ -1,5 +1,10 @@ function rebuildLocalization() { let funcInitString = Game.Init.toString().replaceAll(/[\r\n\t]/g, '') + let GetTooltipFunc = (text, position) => { + let str = position ? Game.getTooltip(text, position) : Game.getTooltip(text) + const mouseOverText = 'onMouseOver="' + return Function('event', str.substring(str.indexOf(mouseOverText) + mouseOverText.length, str.length - '"'.length)) + } // ベーカリー名欄 Game.bakeryNameL.textContent = loc('%1\'s bakery', Game.bakeryName) @@ -22,13 +27,10 @@ function rebuildLocalization() { } // 昇天画面上部メニュー - l('ascendButton').outerHTML = `${loc('Click this once you\'ve bought
everything you need!')}
`, 'bottom-right')} style="font-size:16px;margin-top:0px;">${loc('Reincarnate')}` + l('ascendButton').onmouseover = GetTooltipFunc(`
${loc('Click this once you\'ve bought
everything you need!')}
`, 'bottom-right') + l('ascendButton').children[0].innerHTML = loc('Reincarnate') l('ascendInfo').getElementsByClassName('ascendData')[0].innerHTML = loc('You are ascending.
Drag the screen around
or use arrow keys!
When you\'re ready,
click Reincarnate.') Game.UpdateAscensionModePrompt() - AddEvent(l('ascendButton'), 'click', function() { - PlaySound('snd/tick.mp3') - Game.Reincarnate() - }) // 設定画面オンオフ ON = ' ' + loc('ON') @@ -36,8 +38,8 @@ function rebuildLocalization() { // 施設非表示欄 for (let pm of document.getElementsByClassName('productMute')) { - let id = pm.id.split('productMute')[1] - pm.outerHTML = `
${loc('Mute')}
(${loc('Minimize this building')})
`, 'this')} onclick="Game.ObjectsById[${id}].mute(1);PlaySound(Game.ObjectsById[${id}].muted?\'snd/clickOff2.mp3\':\'snd/clickOn2.mp3\');" id="productMute${id}">${loc('Mute')}` + pm.onmouseover = GetTooltipFunc(`
${loc('Mute')}
(${loc('Minimize this building')})
`, 'this') + pm.innerHTML = loc('Mute') } l('buildingsMute').children[0].innerHTML = loc('Muted:') @@ -169,7 +171,7 @@ function rebuildLocalization() { let name = result[1].replaceAll('\\\'', '\'') let obj = Game.Upgrades[name] let pow = typeof (obj.power) === 'function' ? obj.power(obj) : obj.power - obj.baseDesc = loc('Cookie production multiplier +%1%.', pow) + obj.baseDesc = getStrCookieProductionMultiplierPlus(pow) } // シナジー系アップグレード概要 @@ -180,7 +182,7 @@ function rebuildLocalization() { } // ティアありアップグレード概要 - for (let result of funcInitString.matchAll(/(?.+?<\/q>)?(?.+?<\/q>)?(?permanent across all playthroughs.') @@ -236,32 +238,47 @@ function rebuildLocalization() { let match = result[2].match(/desc\((\d+?)\)/) obj.baseDesc = loc('You retain optimal cookie production while the game is closed for twice as long, for a total of %1.', Game.sayTime(Number(match[1]) * 60 * 60 * Game.fps, -1)) } else { - obj.baseDesc = eval(result[2]) + obj.baseDesc = Function('getStrThousandFingersGain', 'strKittenDesc', 'getStrCookieProductionMultiplierPlus', 'getStrClickingGains', 'return ' + result[2])(getStrThousandFingersGain, strKittenDesc, getStrCookieProductionMultiplierPlus, getStrClickingGains) } } + // Game.lastで翻訳されているアップグレードの再翻訳 + Game.Upgrades['Birthday cookie'].baseDesc = loc('Cookie production multiplier +%1% for every year Cookie Clicker has existed (currently: +%2%).', [1, Beautify(Math.floor((Date.now() - new Date(2013, 7, 8)) / (1000 * 60 * 60 * 24 * 365)))]) + Game.Upgrades['Elderwort biscuits'].baseDesc = `${getStrCookieProductionMultiplierPlus(2)}
${loc('%1 are %2% more powerful.', [cap(Game.Objects['Grandma'].plural), 2])}
${loc('Dropped by %1 plants.', loc('Elderwort').toLowerCase())}` + Game.Upgrades['Bakeberry cookies'].baseDesc = `${getStrCookieProductionMultiplierPlus(2)}
${loc('Dropped by %1 plants.', loc('Bakeberry').toLowerCase())}` + Game.Upgrades['Duketater cookies'].baseDesc = `${getStrCookieProductionMultiplierPlus(10)}
${loc('Dropped by %1 plants.', loc('Duketater').toLowerCase())}` + Game.Upgrades['Green yeast digestives'].baseDesc = `${loc('Golden cookies give %1% more cookies.', 1)}
${loc('Golden cookie effects last %1% longer.', 1)}
${loc('Golden cookies appear %1% more often.', 1)}
${loc('Random drops are %1% more common.', 3)}
${loc('Dropped by %1 plants.', loc('Green rot').toLowerCase())}` + Game.Upgrades['Wheat slims'].baseDesc = `${getStrCookieProductionMultiplierPlus(1)}
${loc('Dropped by %1 plants.', loc('Baker\'s wheat').toLowerCase())}` + + // ゲーム開始時と概要欄が変わってしまうため、バレンタインのアップグレードの再翻訳 + for(let heart of Game.heartDrops) { + let obj = Game.Upgrades[heart] + obj.baseDesc = getStrCookieProductionMultiplierPlus(2) + } + // アップグレードフレーバーテキスト for (let upg in Game.Upgrades) { let obj = Game.Upgrades[upg] + let qpos = obj.baseDesc.indexOf('') + if (qpos >= 0) { + obj.baseDesc = obj.baseDesc.substring(0, qpos) + } + obj.ddesc = BeautifyInText(obj.baseDesc) let quote = loc(FindLocStringByPart('Upgrade quote ' + obj.id)) - if (typeof (quote) !== 'undefined') { - let qpos = obj.baseDesc.indexOf('') - if (qpos >= 0) { - obj.baseDesc = obj.baseDesc.substring(0, qpos) - } + if (quote) { obj.baseDesc += `${quote}` + obj.ddesc += `${quote}` } - obj.ddesc = obj.baseDesc } // ティアあり実績概要 - for (let result of funcInitString.matchAll(/Game.TieredAchievement\('(.+?)(?%1.', loc('%1 ' + obj.buildingTie.bsingle, LBeautify(Game.Tiers[obj.tier].achievUnlock))) } // 施設別生産量実績概要 - for (let result of funcInitString.matchAll(/Game.ProductionAchievement\('(.+?)(?%1 in one ascension.', loc('%1 cookie', { n: obj.threshold, b: toFixed(obj.threshold) })) } // CpS実績概要 - for (let result of funcInitString.matchAll(/Game.CpsAchievement\(('.+?(?%1 per second.', loc('%1 cookie', { n: obj.threshold, b: toFixed(obj.threshold) })) } // その他実績概要 - for (let result of funcInitString.matchAll(/new Game.Achievement\('(.+?)(?') + if (qpos >= 0) { + obj.baseDesc = obj.baseDesc.substring(0, qpos) + } obj.ddesc = BeautifyInText(obj.baseDesc) let quote = loc(FindLocStringByPart('Achievement quote ' + obj.id)) if (typeof (quote) !== 'undefined') { - let qpos = obj.ddesc.indexOf('') - if (qpos >= 0) { - obj.ddesc = obj.ddesc.substring(0, qpos) - } + obj.baseDesc += `${quote}` obj.ddesc += `${quote}` } } - + + // ミニゲーム菜園関連の再翻訳 + let Mg = Game.Objects['Farm'].minigame + funcInitString = Mg.init.toString().replace(/[\r\n\t]/g, '') + // 作物の再翻訳 + let plantsString = funcInitString.match(/M\.plants=\{(.+?)\};/)[1] + for (let res of plantsString.matchAll(/'([^']+?)':\{name:'(.+?)(?${loc('Each time you slot a spirit, you use up one worship swap.
If you have 2 swaps left, the next one will refill after %1.
If you have 1 swap left, the next one will refill after %2.
If you have 0 swaps left, you will get one after %3.
Unslotting a spirit costs no swaps.', [Game.sayTime(60 * 60 * 1 * Game.fps), Game.sayTime(60 * 60 * 4 * Game.fps), Game.sayTime(60 * 60 * 16 * Game.fps)])}`) + + // ミニゲーム在庫市場関連の再翻訳 + Mg = Game.Objects['Bank'].minigame + funcInitString = Mg.init.toString().replaceAll(/[\r\n\t]/g, '') + // オフィスの再翻訳 + let counter = 0 + for (let res of funcInitString.match(/M\.offices=\[(.+?)\];/)[1].matchAll(/{name:loc\("(.+?)"\),.+?,desc:(.+?)},/g)) { + Mg.offices[counter].name = loc(res[1]) + Mg.offices[counter].desc = Function('return ' + res[2])() + counter++ + } + // ローンの再翻訳 + counter = 0 + for (let res of funcInitString.match(/M\.loanTypes=\[(.+?)\];/)[1].matchAll(/\[loc\("(.+?)"\),.+?,loc\("(.+?)"\)\]/g)) { + Mg.loanTypes[counter][0] = loc(res[1]) + Mg.loanTypes[counter][6] = loc(res[2]) + counter++ + } + // メイン画面を再翻訳 + l('bankHeader').children[0].children[0].innerHTML = loc('Profits: %1. All prices are in $econds of your highest raw cookies per second.', '$0') + ' ' + l('bankBrokersBuy').innerHTML = loc('Hire') + for (let i = 1; i <= 3; i++) { + l('bankLoan' + i).innerHTML = loc('Loan #%1', i) + } + let buyStr = loc('Buy') + let sellStr = loc('Sell') + for (let i = 0; i < Mg.goodsById.length; i++) { + let good = Mg.goodsById[i] + good.name = loc(FindLocStringByPart(`STOCK ${i + 1} TYPE`)) + good.symbol = loc(FindLocStringByPart(`STOCK ${i + 1} LOGO`)) + good.company = loc(FindLocStringByPart(`STOCK ${i + 1} NAME`)) + let goodDiv = l('bankGood-' + i) + let bankSymbols = goodDiv.children[0].querySelectorAll('.bankSymbol') + let str = bankSymbols[0].innerHTML + bankSymbols[0].innerHTML = `${good.symbol} ${str.substring(str.indexOf('<'))}` + str = bankSymbols[1].innerHTML + bankSymbols[1].innerHTML = `${loc('value:')} ${str.substring(str.indexOf('<'))}` + str = bankSymbols[2].innerHTML + bankSymbols[2].innerHTML = `${loc('stock:')} ${str.substring(str.indexOf('<'))}` + bankSymbols = goodDiv.children[1].querySelectorAll('.bankSymbol') + for (let j = 0; j <= 1; j++) { + bankSymbols[j].style['display'] = (buyStr.length > 4 || sellStr.length > 4) ? 'block' : '' + bankSymbols[j].style['padding'] = (buyStr.length > 4 || sellStr.length > 4) ? '0px' : '' + bankSymbols[j].style['width'] = (buyStr.length > 4 || sellStr.length > 4) ? '100%' : '' + } + bankSymbols[0].innerHTML = buyStr + bankSymbols[1].innerHTML = sellStr + l(`bankGood-${i}_Max`).innerHTML = cap(loc('max')) + l(`bankGood-${i}_-All`).innerHTML = cap(loc('all')) + } + l('bankGraphLines').innerHTML = loc('Line style') + l('bankGraphCols').innerHTML = loc('Color mode') + if (l('bankCheatSpeeda') != null) { + l('bankCheatSpeeda').innerHTML = loc('Toggle speed') + } + l('bankGraphBox').children[1].innerHTML = loc('DOUGH JONES INDEX') + + // ミニゲーム魔導書関連の再翻訳 + Mg = Game.Objects['Wizard tower'].minigame + // 魔法を再翻訳 + for (let res of Mg.init.toString().replace(/[\r\n\t]/g, '').matchAll(/'((?:[^']|\\')+?)(?${loc('This is your magic meter. Each spell costs magic to use.
Your maximum amount of magic varies depending on your amount of Wizard towers, and their level.
Magic refills over time. The lower your magic meter, the slower it refills.')}`) + Game.RebuildUpgrades() Game.BuildStore() @@ -380,6 +511,50 @@ function rebuildLocalization() { l('smallSupport').children[4].innerHTML = '^ スポンサードリンク ^' l('support').children[0].innerHTML = 'v スポンサードリンク v' 'Cookie Clickerは主に広告によって支えられています。
このサイトをブロックしないよう考えていただくかPatreonを確認してください!' + + // 通知欄の再翻訳 + for (let note of Game.Notes) { + let icon = JSON.stringify(note.pic) + if (icon === JSON.stringify([25, 7])) { + // バックアップ催促の通知 + note.title = loc('Back up your save!') + note.desc = `${loc('Hello again! Just a reminder that you may want to back up your Cookie Clicker save every once in a while, just in case.
To do so, go to Options and hit "Export save" or "Save to file"!')}
${loc('Don\'t show this again')}`.replaceAll('==CLOSETHIS()==', 'Game.CloseNote(' + note.id + ');') + } else if (note.pic[1] === 11 && note.pic[0] >= 0 && note.pic[0] < 16) { + // オフライン中の収入の通知 + let res = note.desc.match(/(\d+)(?:,(\d+)|\.(\d+)( \w+))?/) + let newval + if (res[2]) { + newval = Number(res[1] + res[2]) + } else if(res[3] && res[4]) { + newval = Number(`${res[1]}.${res[3]}`) * 1000 ** (formatLong.indexOf(res[4]) + 1) + } else { + newval = Number(res[1]) + } + note.title = loc('Welcome back!') + note.desc = loc('You earned %1 while you were away.', loc('%1 cookie', LBeautify(newval))) + } else if (icon === JSON.stringify([20, 3])) { + // バレンタインシーズン開始の通知 + note.title = loc('Valentine\'s Day!') + note.desc = loc('It\'s Valentine\'s season!
Love\'s in the air and cookies are just that much sweeter!') + } else if (icon === JSON.stringify([17, 6])) { + // ビジネスシーズン開始の通知 + note.title = loc('Business Day!') + note.desc = loc('It\'s Business season!
Don\'t panic! Things are gonna be looking a little more corporate for a few days.') + } else if (icon === JSON.stringify([13, 8])) { + // ハロウィンシーズン開始の通知 + note.title = loc('Halloween!') + note.desc = loc('It\'s Halloween season!
Everything is just a little bit spookier!') + } else if (icon === JSON.stringify([12, 10])) { + // クリスマスシーズン開始の通知 + note.title = loc('Christmas time!') + note.desc = loc('It\'s Christmas season!
Bring good cheer to all and you just may get cookies in your stockings!') + } else if (icon === JSON.stringify([0, 12])) { + // イースターシーズン開始の通知 + note.title = loc('Easter!') + note.desc = loc('It\'s Easter season!
Keep an eye out and you just might click a rabbit or two!') + } + } + Game.UpdateNotes() } if(typeof betterJapanese !== 'undefined') rebuildLocalization() \ No newline at end of file diff --git a/tools/build-steam.js b/tools/build-steam.js index c073b36..11b1755 100644 --- a/tools/build-steam.js +++ b/tools/build-steam.js @@ -5,7 +5,10 @@ const distDir = path.join(rootDir, './build/') const assetsDir = path.join(rootDir, './src/steam/') const srcDir = path.join(rootDir, './src/common/') +const version = require(path.join(rootDir, './package.json')).version + if (!fs.existsSync(distDir)) fs.mkdirSync(distDir) fs.copySync(srcDir, distDir) -fs.copySync(assetsDir, distDir) \ No newline at end of file +fs.copySync(assetsDir, distDir) +fs.writeJSONSync(path.join(distDir, './version.json'), { version }) \ No newline at end of file diff --git a/tools/build-web.js b/tools/build-web.js index 387de78..c27dd7e 100644 --- a/tools/build-web.js +++ b/tools/build-web.js @@ -6,8 +6,11 @@ const assetsDir = path.join(distDir, './assets/') const srcDir = path.join(rootDir, './src/common/') const webAssetsDir = path.join(rootDir, './src/web/') +const version = require(path.join(rootDir, './package.json')).version + if (!fs.existsSync(distDir)) fs.mkdirSync(distDir) if (!fs.existsSync(assetsDir)) fs.mkdirSync(assetsDir) fs.copySync(srcDir, assetsDir) -fs.copySync(webAssetsDir, distDir) \ No newline at end of file +fs.copySync(webAssetsDir, distDir) +fs.writeJSONSync(path.join(distDir, './version.json'), { version }) \ No newline at end of file diff --git a/tools/start.js b/tools/start.js index f10dc10..3aacef4 100644 --- a/tools/start.js +++ b/tools/start.js @@ -16,6 +16,8 @@ const eslint = new ESLINT() const color = require('chalk') log.enabled = true +const version = require(path.join(rootDir, './package.json')).version + async function initFormatter() { formatter = await eslint.loadFormatter('stylish') } @@ -88,6 +90,8 @@ async function copyFiles(file) { copyFiles() +fs.writeJSONSync(path.join(distDir, './version.json'), { version }) + const watcher = chokidar.watch([srcDir, assetsDir, localeFile]) watcher.on('ready', () => log('ready'))