mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2025-10-30 14:17:55 +00:00
@@ -32,7 +32,8 @@ export interface Config {
|
||||
hardwareAcceleration: boolean
|
||||
accountName: string
|
||||
stashScroll: boolean
|
||||
language: 'en' | 'ru'
|
||||
language: 'en' | 'ru' | 'cmn-Hant'
|
||||
realm: 'pc-ggg' | 'pc-garena'
|
||||
widgets: widget.Widget[]
|
||||
fontSize: number
|
||||
disableUpdateDownload: boolean
|
||||
@@ -82,6 +83,7 @@ export const defaultConfig = (): Config => ({
|
||||
accountName: '',
|
||||
stashScroll: true,
|
||||
language: 'en',
|
||||
realm: 'pc-ggg',
|
||||
fontSize: 16,
|
||||
disableUpdateDownload: false,
|
||||
widgets: [
|
||||
|
||||
@@ -192,6 +192,11 @@ function upgradeConfig (_config: Config): Config {
|
||||
wmId: Math.max(0, ...config.widgets.map(_ => _.wmId)) + 1
|
||||
})
|
||||
|
||||
config.realm = 'pc-ggg'
|
||||
if (config.language === 'zh_TW' as string) {
|
||||
config.language = 'cmn-Hant'
|
||||
}
|
||||
|
||||
config.configVersion = 12
|
||||
}
|
||||
|
||||
|
||||
@@ -94,4 +94,7 @@ export const LANGUAGE_DETECTOR = [{
|
||||
}, {
|
||||
lang: 'ko',
|
||||
firstLine: '아이템 종류: '
|
||||
}, {
|
||||
lang: 'cmn-Hant',
|
||||
firstLine: '物品種類: '
|
||||
}]
|
||||
|
||||
32
renderer/public/data/cmn-Hant/app_i18n.json
Normal file
32
renderer/public/data/cmn-Hant/app_i18n.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
|
||||
"Add": "添加",
|
||||
"Retry": "重試",
|
||||
"Offline": "離線",
|
||||
"Online": "在線",
|
||||
"You": "你",
|
||||
"Browser": "瀏覧器",
|
||||
"Search": "搜尋",
|
||||
"min": "最小",
|
||||
"max": " 最大",
|
||||
"Restart required": "需要重啟",
|
||||
"Save": "保存",
|
||||
"Cancel": "取消",
|
||||
"Enabled": "啟用",
|
||||
"Disabled": "禁用",
|
||||
"No": "否",
|
||||
"Yes": "是",
|
||||
"Remove": "移除",
|
||||
"implicit": "固定",
|
||||
"explicit": "隨機",
|
||||
"enchant": "附魔",
|
||||
"crafted": "工藝",
|
||||
"fractured": "破裂",
|
||||
"scourge": "天災",
|
||||
"Not recognized modifier": "無法使用此詞綴",
|
||||
"Refresh": "刷新",
|
||||
"map.mods.heist": "劫盜",
|
||||
"map.mods.outdated": "過時",
|
||||
"Support development on": "支持開發"
|
||||
|
||||
}
|
||||
92
renderer/public/data/cmn-Hant/client_strings.js
Normal file
92
renderer/public/data/cmn-Hant/client_strings.js
Normal file
@@ -0,0 +1,92 @@
|
||||
// @ts-check
|
||||
/** @type{import('../../../src/assets/data/interfaces').TranslationDict} */
|
||||
export default {
|
||||
RARITY_NORMAL: '普通',
|
||||
RARITY_MAGIC: '魔法',
|
||||
RARITY_RARE: '稀有',
|
||||
RARITY_UNIQUE: '傳奇',
|
||||
RARITY_GEM: '寶石',
|
||||
RARITY_CURRENCY: '通貨',
|
||||
RARITY_DIVCARD: '命運卡',
|
||||
MAP_TIER: '地圖階級: ',
|
||||
RARITY: '稀有度: ',
|
||||
ITEM_CLASS: '物品種類: ',
|
||||
ITEM_LEVEL: '物品等級: ',
|
||||
TALISMAN_TIER: '魔符階級: ',
|
||||
GEM_LEVEL: '等級: ',
|
||||
STACK_SIZE: '堆疊數量: ',
|
||||
SOCKETS: '插槽: ',
|
||||
QUALITY: '品質: ',
|
||||
PHYSICAL_DAMAGE: '物理傷害: ',
|
||||
ELEMENTAL_DAMAGE: '元素傷害: ',
|
||||
CRIT_CHANCE: '暴擊率: ',
|
||||
ATTACK_SPEED: '每秒攻擊次數: ',
|
||||
ARMOUR: '護甲: ',
|
||||
EVASION: '閃避值: ',
|
||||
ENERGY_SHIELD: '能量護盾: ',
|
||||
TAG_WARD: '保護: ',
|
||||
BLOCK_CHANCE: '格擋率: ',
|
||||
CORRUPTED: '已汙染',
|
||||
UNIDENTIFIED: '未鑑定',
|
||||
ITEM_SUPERIOR: /^精良的 (.*)$/,
|
||||
MAP_BLIGHTED: /^凋落的 (.*)$/,
|
||||
MAP_BLIGHT_RAVAGED: /^凋落蔓延的 (.*)$/,
|
||||
INFLUENCE_SHAPER: '塑者之物',
|
||||
INFLUENCE_ELDER: '尊師之物',
|
||||
INFLUENCE_CRUSADER: '聖戰軍王物品',
|
||||
INFLUENCE_HUNTER: '狩獵者物品',
|
||||
INFLUENCE_REDEEMER: '救贖者物品',
|
||||
INFLUENCE_WARLORD: '總督軍物品',
|
||||
SECTION_SYNTHESISED: '追憶之物',
|
||||
ITEM_SYNTHESISED: /^追憶之 (.*)$/,
|
||||
VEILED_PREFIX: '隱匿前綴',
|
||||
VEILED_SUFFIX: '隱匿後綴',
|
||||
FLASK_CHARGES: /^目前有 \d+ 充能次數$/,
|
||||
METAMORPH_HELP: '在塔恩的鍊金室將此與其他四個不同的樣本合成。',
|
||||
BEAST_HELP: '點擊右鍵將此加入你的獸獵寓言。',
|
||||
VOIDSTONE_HELP: '將此放置於你輿圖上的壁壘,來增加地圖階級和揭露該壁壘地區隱藏的地圖。',
|
||||
METAMORPH_BRAIN: /^.* 腦髓$/,
|
||||
METAMORPH_EYE: /^.* 眼睛$/,
|
||||
METAMORPH_LUNG: /^.* 肺臟$/,
|
||||
METAMORPH_HEART: /^.* 心臟$/,
|
||||
METAMORPH_LIVER: /^.* 肝臟$/,
|
||||
CANNOT_USE_ITEM: '你無法使用這項裝備,它的數值將被忽略',
|
||||
QUALITY_ANOMALOUS: /^異常的 (.*)$/,
|
||||
QUALITY_DIVERGENT: /^相異的 (.*)$/,
|
||||
QUALITY_PHANTASMAL: /^幻影的 (.*)$/,
|
||||
AREA_LEVEL: '地區等級: ',
|
||||
HEIST_WINGS_REVEALED: '已揭露側廂: ',
|
||||
HEIST_TARGET: '劫盜目標:',
|
||||
HEIST_BLUEPRINT_ENCHANTS: '附魔裝備',
|
||||
HEIST_BLUEPRINT_TRINKETS: '盜賊的飾品或通貨',
|
||||
HEIST_BLUEPRINT_GEMS: '不尋常寶石',
|
||||
HEIST_BLUEPRINT_REPLICAS: '贗品或實驗性物品',
|
||||
MIRRORED: '已複製',
|
||||
MODIFIER_LINE: /^(?<type>[^"]+)(?:\s+"(?<name>[^"]+)")?(?:\s+\(階層:(?<tier>\d+)\))?(?:\s+\(階級:(?<rank>\d+)\))?$/,
|
||||
PREFIX_MODIFIER: '前綴',
|
||||
SUFFIX_MODIFIER: '後綴',
|
||||
CRAFTED_PREFIX: '大師工藝前綴',
|
||||
CRAFTED_SUFFIX: '大師工藝後綴',
|
||||
UNSCALABLE_VALUE: ' — 無法使用的值',
|
||||
CORRUPTED_IMPLICIT: '已汙染固定詞綴',
|
||||
MODIFIER_INCREASED: /^增加 (.+?)%$/,
|
||||
INCURSION_OPEN: '開啟房間:',
|
||||
INCURSION_OBSTRUCTED: '受阻的房間:',
|
||||
EATER_IMPLICIT: /^吞噬天地固定詞綴 \((?<rank>.+)\)$/,
|
||||
EXARCH_IMPLICIT: /^灼烙總督固定詞綴 \((?<rank>.+)\)$/,
|
||||
ELDRITCH_MOD_R1: '低階',
|
||||
ELDRITCH_MOD_R2: '高階',
|
||||
ELDRITCH_MOD_R3: '宏偉',
|
||||
ELDRITCH_MOD_R4: '卓越',
|
||||
ELDRITCH_MOD_R5: '精緻',
|
||||
ELDRITCH_MOD_R6: '完美',
|
||||
// ---
|
||||
CHAT_SYSTEM: /^: (?<body>.+)$/,
|
||||
CHAT_TRADE: /^\$(?:<(?<guild_tag>.+?)> )?(?<char_name>.+?): (?<body>.+)$/,
|
||||
CHAT_GLOBAL: /^#(?:<(?<guild_tag>.+?)> )?(?<char_name>.+?): (?<body>.+)$/,
|
||||
CHAT_PARTY: /^%(?:<(?<guild_tag>.+?)> )?(?<char_name>.+?): (?<body>.+)$/,
|
||||
CHAT_GUILD: /^&(?:<(?<guild_tag>.+?)> )?(?<char_name>.+?): (?<body>.+)$/,
|
||||
CHAT_WHISPER_TO: /^@向 (?<char_name>.+?): (?<body>.+)$/,
|
||||
CHAT_WHISPER_FROM: /^@來自 (?:<(?<guild_tag>.+?)> )?(?<char_name>.+?): (?<body>.+)$/,
|
||||
CHAT_WEBTRADE_GEM: /^等級 (?<gem_lvl>\d+) (?<gem_qual>\d+)% (?<gem_name>.+)$/
|
||||
}
|
||||
3921
renderer/public/data/cmn-Hant/items.ndjson
Normal file
3921
renderer/public/data/cmn-Hant/items.ndjson
Normal file
File diff suppressed because it is too large
Load Diff
6126
renderer/public/data/cmn-Hant/stats.ndjson
Normal file
6126
renderer/public/data/cmn-Hant/stats.ndjson
Normal file
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
@@ -4,7 +4,7 @@ import fnv1a from '@bensjoberg/fnv1a'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
const LANGUAGES = ['en', 'ru']
|
||||
const LANGUAGES = ['en', 'ru', 'cmn-Hant']
|
||||
|
||||
for (const lang of LANGUAGES) {
|
||||
const lineStarts = {
|
||||
|
||||
@@ -28,3 +28,14 @@ export function updateConfig (updates: Config) {
|
||||
export function saveConfig () {
|
||||
MainProcess.saveConfig(JSON.parse(JSON.stringify(AppConfig())))
|
||||
}
|
||||
|
||||
export function poeWebApi () {
|
||||
const { language, realm } = AppConfig()
|
||||
switch (language) {
|
||||
case 'en': return 'www.pathofexile.com'
|
||||
case 'ru': return 'ru.pathofexile.com'
|
||||
case 'cmn-Hant': return (realm === 'pc-garena')
|
||||
? 'web.poe.garena.tw'
|
||||
: 'www.pathofexile.com'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { AppConfig } from '@/web/Config'
|
||||
import { AppConfig, poeWebApi } from '@/web/Config'
|
||||
import { MainProcess } from './IPC'
|
||||
|
||||
export const PERMANENT_LEAGUE_IDS = [
|
||||
// pc-ggg
|
||||
'Standard', 'Hardcore',
|
||||
// pc-garena
|
||||
'標準模式', '專家模式'
|
||||
]
|
||||
|
||||
export const isLoading = ref(false)
|
||||
export const error = ref<string | null>(null)
|
||||
@@ -28,7 +36,7 @@ export async function load () {
|
||||
error.value = null
|
||||
|
||||
try {
|
||||
const response = await fetch('https://api.pathofexile.com/leagues?type=main&realm=pc')
|
||||
const response = await fetch(`${MainProcess.CORS}https://${poeWebApi()}/api/leagues?type=main&realm=pc`)
|
||||
if (!response.ok) throw new Error(JSON.stringify(Object.fromEntries(response.headers)))
|
||||
const leagues: Array<{ id: string, rules: Array<{ id: string }> }> = await response.json()
|
||||
tradeLeagues.value = leagues.filter(league => !league.rules.some(rule => rule.id === 'NoParties'))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { shallowRef, watch } from 'vue'
|
||||
import { AppConfig } from '@/web/Config'
|
||||
import { MainProcess } from '@/web/background/IPC'
|
||||
import { selected as selectedLeague, isPublic as isPublicLeague } from './Leagues'
|
||||
|
||||
@@ -19,7 +20,7 @@ const RETRY_TIME = 2 * 60 * 1000
|
||||
const UPDATE_TIME = 16 * 60 * 1000
|
||||
|
||||
async function load (force: boolean = false) {
|
||||
if (!selectedLeague.value || !isPublicLeague.value) return
|
||||
if (!selectedLeague.value || !isPublicLeague.value || AppConfig().realm !== 'pc-ggg') return
|
||||
const leagueAtStartOfLoad = selectedLeague.value
|
||||
|
||||
if (!force && (Date.now() - lastUpdateTime) < UPDATE_TIME) return
|
||||
|
||||
@@ -124,17 +124,19 @@ export function handleLine (line: string) {
|
||||
}
|
||||
|
||||
const TRADE_WHISPER = {
|
||||
en: /^Hi, I would like to buy your (?<item>.+) listed for (?<price>.+) in (?<league>.+) \(stash tab "(?<tab_name>.*)"; position: left (?<tab_left>\d+), top (?<tab_top>\d+)\)(?<message>.+)?$/,
|
||||
ru: /^Здравствуйте, хочу купить у вас (?<item>.+) за (?<price>.+) в лиге (?<league>.+) \(секция "(?<tab_name>.*)"; позиция: (?<tab_left>\d+) столбец, (?<tab_top>\d+) ряд\)(?<message>.+)?$/,
|
||||
ko: /^안녕하세요, (?<league>.+)\(보관함 탭 "(?<tab_name>.*)", 위치: 왼쪽 (?<tab_left>\d+), 상단 (?<tab_top>\d+)\)에 (?<price>.+)\(으\)로 올려놓은 (?<item>.+)\(을\)를 구매하고 싶습니다(?<message>.+)?$/,
|
||||
de: /^Hi, ich möchte '(?<item>.+)' zum angebotenen Preis von (?<price>.+) in der (?<league>.+)-Liga kaufen \(Truhenfach "(?<tab_name>.*)"; Position: (?<tab_left>\d+) von links, (?<tab_top>\d+) von oben\)(?<message>.+)?$/,
|
||||
fr: /^Bonjour, je souhaiterais t'acheter (?<item>.+) pour (?<price>.+) dans la ligue (?<league>.+) \(onglet de réserve "(?<tab_name>.*)" ; (?<tab_left>\d+)e en partant de la gauche, (?<tab_top>\d+)e en partant du haut\)(?<message>.+)?$/,
|
||||
es: /^Hola, quisiera comprar tu (?<item>.+) listado por (?<price>.+) en (?<league>.+) \(pestaña de alijo "(?<tab_name>.*)"; posición: izquierda(?<tab_left>\d+), arriba (?<tab_top>\d+)\)(?<message>.+)?$/,
|
||||
pt: /^Olá, eu gostaria de comprar o seu item (?<item>.+) listado por (?<price>.+) na (?<league>.+) \(aba do baú: "(?<tab_name>.*)"; posição: esquerda (?<tab_left>\d+), topo (?<tab_top>\d+)\)(?<message>.+)?$/,
|
||||
th: /^สวัสดี, เราต้องการจะชื้อของคุณ (?<item>.+) ใน ราคา (?<price>.+) ใน (?<league>.+) \(stash tab "(?<tab_name>.*)"; ตำแหน่ง: ซ้าย (?<tab_left>\d+), บน (?<tab_top>\d+)\)(?<message>.+)?$/
|
||||
'en': /^Hi, I would like to buy your (?<item>.+) listed for (?<price>.+) in (?<league>.+) \(stash tab "(?<tab_name>.*)"; position: left (?<tab_left>\d+), top (?<tab_top>\d+)\)(?<message>.+)?$/,
|
||||
'ru': /^Здравствуйте, хочу купить у вас (?<item>.+) за (?<price>.+) в лиге (?<league>.+) \(секция "(?<tab_name>.*)"; позиция: (?<tab_left>\d+) столбец, (?<tab_top>\d+) ряд\)(?<message>.+)?$/,
|
||||
'ko': /^안녕하세요, (?<league>.+)\(보관함 탭 "(?<tab_name>.*)", 위치: 왼쪽 (?<tab_left>\d+), 상단 (?<tab_top>\d+)\)에 (?<price>.+)\(으\)로 올려놓은 (?<item>.+)\(을\)를 구매하고 싶습니다(?<message>.+)?$/,
|
||||
'de': /^Hi, ich möchte '(?<item>.+)' zum angebotenen Preis von (?<price>.+) in der (?<league>.+)-Liga kaufen \(Truhenfach "(?<tab_name>.*)"; Position: (?<tab_left>\d+) von links, (?<tab_top>\d+) von oben\)(?<message>.+)?$/,
|
||||
'fr': /^Bonjour, je souhaiterais t'acheter (?<item>.+) pour (?<price>.+) dans la ligue (?<league>.+) \(onglet de réserve "(?<tab_name>.*)" ; (?<tab_left>\d+)e en partant de la gauche, (?<tab_top>\d+)e en partant du haut\)(?<message>.+)?$/,
|
||||
'es': /^Hola, quisiera comprar tu (?<item>.+) listado por (?<price>.+) en (?<league>.+) \(pestaña de alijo "(?<tab_name>.*)"; posición: izquierda(?<tab_left>\d+), arriba (?<tab_top>\d+)\)(?<message>.+)?$/,
|
||||
'pt': /^Olá, eu gostaria de comprar o seu item (?<item>.+) listado por (?<price>.+) na (?<league>.+) \(aba do baú: "(?<tab_name>.*)"; posição: esquerda (?<tab_left>\d+), topo (?<tab_top>\d+)\)(?<message>.+)?$/,
|
||||
'th': /^สวัสดี, เราต้องการจะชื้อของคุณ (?<item>.+) ใน ราคา (?<price>.+) ใน (?<league>.+) \(stash tab "(?<tab_name>.*)"; ตำแหน่ง: ซ้าย (?<tab_left>\d+), บน (?<tab_top>\d+)\)(?<message>.+)?$/,
|
||||
'cmn-Hant': /^你好,我想購買 (?<item>.+) 標價 (?<price>.+) 在 (?<league>.+) \(倉庫頁 "(?<tab_name>.*)"; 位置: 左 (?<tab_left>\d+), 上 (?<tab_top>\d+)\)(?<message>.+)?$/
|
||||
}
|
||||
|
||||
const TRADE_BULK_WHISPER = {
|
||||
en: /^Hi, I'd like to buy your (?<item>.+) for my (?<price>.+) in (?<league>.+)\.(?<message>.+)?$/,
|
||||
ru: /^Здравствуйте, хочу купить у вас (?<item>.+) за (?<price>.+) в лиге (?<league>.+)\.(?<message>.+)?$/
|
||||
'en': /^Hi, I'd like to buy your (?<item>.+) for my (?<price>.+) in (?<league>.+)\.(?<message>.+)?$/,
|
||||
'ru': /^Здравствуйте, хочу купить у вас (?<item>.+) за (?<price>.+) в лиге (?<league>.+)\.(?<message>.+)?$/,
|
||||
'cmn-Hant': /^你好,我想用 (?<price>.+) 購買 (?<item>.+) in (?<league>.+)\.(?<message>.+)?$/
|
||||
}
|
||||
|
||||
@@ -74,6 +74,9 @@ export default defineComponent({
|
||||
"ru": {
|
||||
"Item has no modifiers.": "На предмете нету модов.",
|
||||
"has_outdated": "Перевод некоторых свойств был изменен. Проверьте и обновите опасные моды карт в настройках. (Это сообщение будет скрыто, как только вы удалите все устаревшие переводы)"
|
||||
},
|
||||
"cmn-Hant" :{
|
||||
"has_outdataed" :"部份詞綴描述已變更,請檢查並更新地圖的危險詞綴。(當你刪除將所有舊版詞綴,此訊息會隱藏)"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import { parseClipboard } from '@/parser'
|
||||
import { AppConfig } from '@/web/Config'
|
||||
|
||||
const ENDPOINT_BY_LANG = {
|
||||
en: 'www.poewiki.net/wiki',
|
||||
ru: 'pathofexile-ru.gamepedia.com'
|
||||
}
|
||||
|
||||
export function openWiki (clipboard: string) {
|
||||
const item = parseClipboard(clipboard)
|
||||
if (!item) return
|
||||
|
||||
window.open(`https://${ENDPOINT_BY_LANG[AppConfig().language]}/${item.info.name}`)
|
||||
window.open(`https://www.poewiki.net/wiki/${item.info.refName}`)
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ export default defineComponent({
|
||||
setup () {
|
||||
loadLeagues()
|
||||
|
||||
document.documentElement.lang = AppConfig().language
|
||||
|
||||
const active = shallowRef(false)
|
||||
const gameFocused = shallowRef(false)
|
||||
const hideUI = shallowRef(false)
|
||||
|
||||
@@ -103,7 +103,8 @@ export default defineComponent({
|
||||
chaosPriceThreshold: widget.value.chaosPriceThreshold,
|
||||
collapseListings: widget.value.collapseListings,
|
||||
activateStockFilter: widget.value.activateStockFilter,
|
||||
searchStatRange: widget.value.searchStatRange
|
||||
searchStatRange: widget.value.searchStatRange,
|
||||
useEn: (AppConfig().language === 'cmn-Hant' && AppConfig().realm === 'pc-ggg')
|
||||
})
|
||||
|
||||
if ((!props.advancedCheck && !widget.value.smartInitialSearch) ||
|
||||
|
||||
@@ -88,7 +88,30 @@ export default defineComponent({
|
||||
"Redeemer": "Избавительница",
|
||||
"Warlord": "Вождь",
|
||||
|
||||
"Superior": "Высокого к-ва"
|
||||
"Superior": "Высокого к-ва",
|
||||
"Anomalous": "Аномальный",
|
||||
"Divergent": "Искривлённый",
|
||||
"Phantasmal": "Фантомный"
|
||||
},
|
||||
"cmn-Hant": {
|
||||
"Unidentified": "未鑑定",
|
||||
"Veiled": "隱匿",
|
||||
"Blighted": "凋落",
|
||||
"Blight-ravaged": "凋落蔓延的",
|
||||
"Mirrored": "已複製",
|
||||
"Not Mirrored": "未複製",
|
||||
|
||||
"Shaper": "塑界者",
|
||||
"Elder": "尊師",
|
||||
"Crusader": "聖戰軍王",
|
||||
"Hunter": "狩獵者",
|
||||
"Redeemer": "救贖者",
|
||||
"Warlord": "總督軍",
|
||||
|
||||
"Superior": "精良",
|
||||
"Anomalous": "異常",
|
||||
"Divergent": "相異",
|
||||
"Phantasmal": "幻影"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -135,6 +135,17 @@ export default defineComponent({
|
||||
"White:": "Белые:",
|
||||
"Quality:": "Качество:",
|
||||
"Level:": "Уровень:"
|
||||
},
|
||||
"cmn-Hant": {
|
||||
"Item Level:": "物品等級:",
|
||||
"Stock:": "堆疊數量:",
|
||||
"Map Tier:": "地圖階級:",
|
||||
"Area Level:": "地區等級:",
|
||||
"Wings Revealed:": "展翅:",
|
||||
"Links:": "連線:",
|
||||
"White:": "白:",
|
||||
"Quality:": "品質:",
|
||||
"Level:": "等級:"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -408,6 +408,34 @@ export default defineComponent({
|
||||
"1 Empty or Crafted Modifier": "1 свободное или ремесленное свойство",
|
||||
"Select only if item has 6 modifiers (1 of which is crafted) or if it has 5 modifiers": "Выбирайте, только если у предмета 6 свойств (1 из которых ремесленное) или если у него 5 свойств",
|
||||
"First ask yourself: would you buy an item with this stat?": "Сначала спросите себя: купили бы вы предмет с этим модом?"
|
||||
},
|
||||
"cmn-Hant": {
|
||||
"Q {0}%": "品質: {0}%",
|
||||
"DPS: #": "DPS: #",
|
||||
"Elemental DPS: #": "元素 DPS: #",
|
||||
"Physical DPS: #": "物理 DPS: #",
|
||||
"Attacks per Second: #": "攻擊次數/秒: #",
|
||||
"Critical Strike Chance: #%": "暴擊率: #%",
|
||||
"Armour: #": "護甲: #",
|
||||
"Evasion Rating: #": "閃避: #",
|
||||
"Energy Shield: #": "能量護盾: #",
|
||||
"Ward: #": "保護: #",
|
||||
"Block: #%": "格檔: #%",
|
||||
"variant": "種類",
|
||||
"corrupted": "已汙染",
|
||||
"synthesised": "追憶",
|
||||
"eldritch": "異能",
|
||||
"pseudo": "偽屬性",
|
||||
"Roll is not variable": "數值不可變",
|
||||
"Elemental damage is not the main source of DPS": "元素傷害不是主要DPS來源",
|
||||
"Physical damage is not the main source of DPS": "物理傷害不是主要DPS來源",
|
||||
"Filtering by exact Elemental Resistance unreasonably increases the price": "若是精確的使用各元素抗性查詢價格,查詢結果會過高",
|
||||
"Crafted Chaos Resistance without Explicit mod has no value": "單獨的工藝混沌抗性是沒有價值的",
|
||||
"Buyer will likely change anointment": "買家可能會更改塗油",
|
||||
"Select only if price-checking as base item for crafting": "當你只想查詢基底價格的時候才選取",
|
||||
"1 Empty or Crafted Modifier": "1個空詞綴或是工藝詞綴",
|
||||
"Select only if item has 6 modifiers (1 of which is crafted) or if it has 5 modifiers": "當物品有6個詞綴(其中1個是工藝詞綴),或是5個詞綴才選取",
|
||||
"First ask yourself: would you buy an item with this stat?": "你會買有這樣屬性的物品嗎?"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -186,6 +186,17 @@ export default defineComponent({
|
||||
|
||||
"Pseudo": "Псевдо",
|
||||
"Base item": "База предмета"
|
||||
},
|
||||
"cmn-Hant": {
|
||||
"Hidden": "被隱藏",
|
||||
"Collapse": "折疊",
|
||||
"Stats ignored": "忽略詞綴",
|
||||
"{0} of {1}, stats": "詞綴: {0}/{1}",
|
||||
"Mods": "Mods",
|
||||
"No relevant stats were found": "找不到詞綴",
|
||||
|
||||
"Pseudo": "偽屬性",
|
||||
"Base item": "物品基底"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -2,20 +2,23 @@ import type { ItemFilters } from './interfaces'
|
||||
import { ParsedItem, ItemCategory, ItemRarity, ItemInfluence } from '@/parser'
|
||||
import { tradeTag, PERMANENT_LEAGUES } from '../trade/common'
|
||||
import { ModifierType } from '@/parser/modifiers'
|
||||
import { ITEM_BY_REF } from '@/assets/data'
|
||||
import { BaseType, ITEM_BY_REF } from '@/assets/data'
|
||||
import { CATEGORY_TO_TRADE_ID } from '../trade/pathofexile-trade'
|
||||
|
||||
export const SPECIAL_SUPPORT_GEM = ['Empower Support', 'Enlighten Support', 'Enhance Support']
|
||||
|
||||
interface CreateOptions {
|
||||
league: string
|
||||
chaosPriceThreshold: number
|
||||
collapseListings: 'app' | 'api'
|
||||
activateStockFilter: boolean
|
||||
exact: boolean
|
||||
useEn: boolean
|
||||
}
|
||||
|
||||
export function createFilters (
|
||||
item: ParsedItem,
|
||||
opts: {
|
||||
league: string
|
||||
chaosPriceThreshold: number
|
||||
collapseListings: 'app' | 'api'
|
||||
activateStockFilter: boolean
|
||||
exact: boolean
|
||||
}
|
||||
opts: CreateOptions
|
||||
): ItemFilters {
|
||||
const filters: ItemFilters = {
|
||||
searchExact: {},
|
||||
@@ -30,12 +33,12 @@ export function createFilters (
|
||||
}
|
||||
|
||||
if (item.category === ItemCategory.Gem) {
|
||||
return createGemFilters(item, filters)
|
||||
return createGemFilters(item, filters, opts)
|
||||
}
|
||||
if (item.category === ItemCategory.CapturedBeast) {
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: item.info.refName
|
||||
baseTypeTrade: item.info.refName // NOTE: always English on trade
|
||||
}
|
||||
return filters
|
||||
}
|
||||
@@ -47,13 +50,15 @@ export function createFilters (
|
||||
}
|
||||
if (item.category === ItemCategory.Invitation) {
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: t(opts, item.info)
|
||||
}
|
||||
return filters
|
||||
}
|
||||
if (item.category === ItemCategory.MetamorphSample) {
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: t(opts, item.info)
|
||||
}
|
||||
filters.itemLevel = {
|
||||
value: item.itemLevel!,
|
||||
@@ -67,7 +72,8 @@ export function createFilters (
|
||||
item.info.refName === 'Charged Compass'
|
||||
) {
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: t(opts, item.info)
|
||||
}
|
||||
if (item.info.refName === 'Chronicle of Atzoatl') {
|
||||
filters.areaLevel = {
|
||||
@@ -82,12 +88,14 @@ export function createFilters (
|
||||
if (item.rarity === ItemRarity.Unique && item.info.unique) {
|
||||
filters.searchExact = {
|
||||
name: item.info.name,
|
||||
baseType: ITEM_BY_REF('ITEM', item.info.unique.base)![0].name
|
||||
nameTrade: t(opts, item.info),
|
||||
baseTypeTrade: t(opts, ITEM_BY_REF('ITEM', item.info.unique.base)![0])
|
||||
}
|
||||
} else {
|
||||
const isOccupiedBy = item.statsByType.some(calc => calc.stat.ref === 'Map is occupied by #')
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: t(opts, item.info)
|
||||
}
|
||||
filters.searchRelaxed = {
|
||||
category: item.category,
|
||||
@@ -105,7 +113,8 @@ export function createFilters (
|
||||
}
|
||||
} else if (item.info.refName === 'Expedition Logbook') {
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: t(opts, item.info)
|
||||
}
|
||||
filters.areaLevel = {
|
||||
value: floorToBracket(item.areaLevel!, [1, 68, 73, 78, 81]),
|
||||
@@ -113,7 +122,8 @@ export function createFilters (
|
||||
}
|
||||
} else if (item.category === ItemCategory.HeistContract) {
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: t(opts, item.info)
|
||||
}
|
||||
} else if (item.category === ItemCategory.HeistBlueprint) {
|
||||
filters.searchRelaxed = {
|
||||
@@ -121,7 +131,8 @@ export function createFilters (
|
||||
disabled: true // TODO: blocked by https://www.pathofexile.com/forum/view-thread/3109852
|
||||
}
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: t(opts, item.info)
|
||||
}
|
||||
|
||||
filters.areaLevel = {
|
||||
@@ -140,7 +151,8 @@ export function createFilters (
|
||||
item.rarity !== ItemRarity.Unique
|
||||
) {
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: t(opts, item.info)
|
||||
}
|
||||
filters.searchRelaxed = {
|
||||
category: item.category,
|
||||
@@ -149,11 +161,13 @@ export function createFilters (
|
||||
} else if (item.rarity === ItemRarity.Unique && item.info.unique) {
|
||||
filters.searchExact = {
|
||||
name: item.info.name,
|
||||
baseType: ITEM_BY_REF('ITEM', item.info.unique.base)![0].name
|
||||
nameTrade: t(opts, item.info),
|
||||
baseTypeTrade: t(opts, ITEM_BY_REF('ITEM', item.info.unique.base)![0])
|
||||
}
|
||||
} else {
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: t(opts, item.info)
|
||||
}
|
||||
if (item.category && CATEGORY_TO_TRADE_ID.has(item.category)) {
|
||||
filters.searchRelaxed = {
|
||||
@@ -294,14 +308,21 @@ export function createFilters (
|
||||
return filters
|
||||
}
|
||||
|
||||
function createGemFilters (item: ParsedItem, filters: ItemFilters) {
|
||||
function createGemFilters (
|
||||
item: ParsedItem,
|
||||
filters: ItemFilters,
|
||||
opts: CreateOptions
|
||||
) {
|
||||
filters.searchExact = {
|
||||
baseType: item.info.name
|
||||
baseType: item.info.name,
|
||||
baseTypeTrade: t(opts, item.info)
|
||||
}
|
||||
|
||||
if (item.info.gem!.vaal) {
|
||||
const normalGem = ITEM_BY_REF('GEM', item.info.gem!.normalVariant!)![0]
|
||||
filters.searchRelaxed = {
|
||||
baseType: ITEM_BY_REF('GEM', item.info.gem!.normalVariant!)![0].name,
|
||||
baseType: normalGem.name,
|
||||
baseTypeTrade: t(opts, normalGem),
|
||||
disabled: true
|
||||
}
|
||||
}
|
||||
@@ -362,6 +383,10 @@ function createGemFilters (item: ParsedItem, filters: ItemFilters) {
|
||||
return filters
|
||||
}
|
||||
|
||||
function t (opts: CreateOptions, info: BaseType) {
|
||||
return (opts.useEn) ? info.refName : info.name
|
||||
}
|
||||
|
||||
function floorToBracket (value: number, brackets: readonly number[]) {
|
||||
let prev = brackets[0]
|
||||
for (const num of brackets) {
|
||||
|
||||
@@ -14,6 +14,7 @@ export function createPresets (
|
||||
collapseListings: 'app' | 'api'
|
||||
activateStockFilter: boolean
|
||||
searchStatRange: number
|
||||
useEn: boolean
|
||||
}
|
||||
): { presets: FilterPreset[], active: string } {
|
||||
if (item.info.refName === 'Expedition Logbook') {
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface FilterPreset {
|
||||
|
||||
interface SearchFilter {
|
||||
name?: string
|
||||
nameTrade?: string
|
||||
baseType?: string
|
||||
baseTypeTrade?: string
|
||||
category?: ItemCategory
|
||||
|
||||
@@ -4,8 +4,8 @@ import { AppConfig } from '@/web/Config'
|
||||
import type { PriceCheckWidget } from '@/web/overlay/interfaces'
|
||||
import { RateLimiter } from './RateLimiter'
|
||||
import { ParsedItem, ItemCategory } from '@/parser'
|
||||
|
||||
export const PERMANENT_LEAGUES = ['Standard', 'Hardcore']
|
||||
export { poeWebApi as getTradeEndpoint } from '@/web/Config'
|
||||
export { PERMANENT_LEAGUE_IDS as PERMANENT_LEAGUES } from '@/web/background/Leagues'
|
||||
|
||||
export interface Account {
|
||||
name: string
|
||||
@@ -48,15 +48,6 @@ export function tradeTag (item: ParsedItem): string | undefined {
|
||||
return item.info.tradeTag
|
||||
}
|
||||
|
||||
const ENDPOINT_BY_LANG = {
|
||||
en: 'www.pathofexile.com',
|
||||
ru: 'ru.pathofexile.com'
|
||||
}
|
||||
|
||||
export function getTradeEndpoint (): string {
|
||||
return ENDPOINT_BY_LANG[AppConfig().language]
|
||||
}
|
||||
|
||||
export const RATE_LIMIT_RULES = {
|
||||
SEARCH: shallowReactive(new Set([
|
||||
new RateLimiter(1, 5)
|
||||
|
||||
@@ -260,12 +260,16 @@ export function createTradeRequest (filters: ItemFilters, stats: StatFilter[], i
|
||||
? filters.searchRelaxed
|
||||
: filters.searchExact
|
||||
|
||||
if (activeSearch.name) {
|
||||
if (activeSearch.nameTrade) {
|
||||
query.name = nameToQuery(activeSearch.nameTrade, filters)
|
||||
} else if (activeSearch.name) {
|
||||
query.name = nameToQuery(activeSearch.name, filters)
|
||||
}
|
||||
|
||||
if (activeSearch.baseType) {
|
||||
query.type = nameToQuery(activeSearch.baseTypeTrade ?? activeSearch.baseType, filters)
|
||||
if (activeSearch.baseTypeTrade) {
|
||||
query.type = nameToQuery(activeSearch.baseTypeTrade, filters)
|
||||
} else if (activeSearch.baseType) {
|
||||
query.type = nameToQuery(activeSearch.baseType, filters)
|
||||
}
|
||||
|
||||
if (filters.rarity) {
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
<template>
|
||||
<div class="max-w-md p-2">
|
||||
<div class="mb-4">
|
||||
<div class="flex-1 mb-1">{{ t('Language') }} <span class="bg-gray-200 text-gray-900 rounded px-1">{{ t('Restart required') }}</span></div>
|
||||
<div class="flex gap-x-4">
|
||||
<ui-radio v-model="language" value="en">English</ui-radio>
|
||||
<ui-radio v-model="language" value="ru">Русский</ui-radio>
|
||||
<ui-radio v-model="language" value="cmn-Hant">正體中文</ui-radio>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4" v-if="language === 'cmn-Hant'">
|
||||
<div class="flex-1 mb-1">{{ t('Realm') }}</div>
|
||||
<div class="flex gap-x-4">
|
||||
<ui-radio v-model="realm" value="pc-ggg">{{ t('International') }}</ui-radio>
|
||||
<ui-radio v-model="realm" value="pc-garena">{{ t('Garena') }}</ui-radio>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div class="flex-1 mb-1">{{ t('Font size') }} <span class="bg-gray-200 text-gray-900 rounded px-1">{{ t('Restart required') }}</span></div>
|
||||
<div class="mb-4 flex">
|
||||
@@ -8,21 +23,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div class="flex-1 mb-1">{{ t('Clicking on background focuses game') }}</div>
|
||||
<div class="flex-1 mb-1">{{ t('Auto-download updates') }}</div>
|
||||
<div class="mb-4 flex">
|
||||
<ui-radio v-model="overlayBackgroundClose" :value="false" class="mr-4">{{ t('No') }}</ui-radio>
|
||||
<ui-radio v-model="overlayBackgroundClose" :value="true" class="mr-4">{{ t('Yes') }}</ui-radio>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div class="flex-1 mb-1">{{ t('Background, when APT window is clickable') }}</div>
|
||||
<div class="mb-1 flex">
|
||||
<input v-model="overlayBackground" class="rounded bg-gray-900 px-1 block w-48 mb-1 mr-4 font-poe text-center" />
|
||||
<ui-radio v-model="overlayBackground" value="rgba(255, 255, 255, 0)">{{ t('Transparent') }}</ui-radio>
|
||||
</div>
|
||||
<div class="mb-4" v-if="overlayBackground !== 'rgba(255, 255, 255, 0)'">
|
||||
<ui-radio v-model="overlayBackgroundExclusive" :value="true" class="mr-4">{{ t('Show for Overlay and Price Check') }}</ui-radio><br>
|
||||
<ui-radio v-model="overlayBackgroundExclusive" :value="false">{{ t('Show only for Overlay') }}</ui-radio>
|
||||
<ui-radio v-model="disableUpdateDownload" :value="false" class="mr-4">{{ t('Yes') }}</ui-radio>
|
||||
<ui-radio v-model="disableUpdateDownload" :value="true" class="mr-4">{{ t('No') }}</ui-radio>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
@@ -44,24 +48,28 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div class="flex-1 mb-1">{{ t('Language') }} <span class="bg-gray-200 text-gray-900 rounded px-1">{{ t('Restart required') }}</span></div>
|
||||
<div class="mb-4 flex">
|
||||
<ui-radio v-model="language" value="en" class="mr-4">English</ui-radio>
|
||||
<ui-radio v-model="language" value="ru" class="mr-4">Русский</ui-radio>
|
||||
<div class="flex-1 mb-1">{{ t('Background, when APT window is clickable') }}</div>
|
||||
<div class="mb-1 flex">
|
||||
<input v-model="overlayBackground" class="rounded bg-gray-900 px-1 block w-48 mb-1 mr-4 font-poe text-center" />
|
||||
<ui-radio v-model="overlayBackground" value="rgba(255, 255, 255, 0)">{{ t('Transparent') }}</ui-radio>
|
||||
</div>
|
||||
<div class="mb-4" v-if="overlayBackground !== 'rgba(255, 255, 255, 0)'">
|
||||
<ui-radio v-model="overlayBackgroundExclusive" :value="true" class="mr-4">{{ t('Show for Overlay and Price Check') }}</ui-radio><br>
|
||||
<ui-radio v-model="overlayBackgroundExclusive" :value="false">{{ t('Show only for Overlay') }}</ui-radio>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div class="flex-1 mb-1">{{ t('Auto-download updates') }}</div>
|
||||
<div class="flex-1 mb-1">{{ t('Clicking on background focuses game') }}</div>
|
||||
<div class="mb-4 flex">
|
||||
<ui-radio v-model="disableUpdateDownload" :value="false" class="mr-4">{{ t('Yes') }}</ui-radio>
|
||||
<ui-radio v-model="disableUpdateDownload" :value="true" class="mr-4">{{ t('No') }}</ui-radio>
|
||||
<ui-radio v-model="overlayBackgroundClose" :value="false" class="mr-4">{{ t('No') }}</ui-radio>
|
||||
<ui-radio v-model="overlayBackgroundClose" :value="true" class="mr-4">{{ t('Yes') }}</ui-radio>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { configModelValue, configProp } from './utils'
|
||||
|
||||
@@ -79,7 +87,16 @@ export default defineComponent({
|
||||
overlayBackgroundExclusive: configModelValue(() => props.config, 'overlayBackgroundExclusive'),
|
||||
clientLog: configModelValue(() => props.config, 'clientLog'),
|
||||
gameConfig: configModelValue(() => props.config, 'gameConfig'),
|
||||
language: configModelValue(() => props.config, 'language'),
|
||||
language: computed<typeof props.config.language>({
|
||||
get () { return props.config.language },
|
||||
set (value) {
|
||||
props.config.language = value
|
||||
if (value !== 'cmn-Hant') {
|
||||
props.config.realm = 'pc-ggg'
|
||||
}
|
||||
}
|
||||
}),
|
||||
realm: configModelValue(() => props.config, 'realm'),
|
||||
disableUpdateDownload: configModelValue(() => props.config, 'disableUpdateDownload'),
|
||||
handleLogFile (e: InputEvent) {
|
||||
props.config.clientLog = (e.target as HTMLInputElement).files![0].path
|
||||
@@ -106,6 +123,11 @@ export default defineComponent({
|
||||
"PoE config file": "Файл настроек PoE",
|
||||
"Browse": "Выбрать",
|
||||
"Auto-download updates": "Автозагрузка обновлений"
|
||||
},
|
||||
"cmn-Hant": {
|
||||
"Language": "語言",
|
||||
"Realm": "分流",
|
||||
"International": "國際"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -96,6 +96,18 @@ export default defineComponent({
|
||||
"Item info": "Проверка предмета",
|
||||
"Stash tab scrolling": "Прокрутка вкладок тайника",
|
||||
"Delve grid": "Сетка \"Спуска\""
|
||||
},
|
||||
"cmn-Hant": {
|
||||
"You can clear hotkey by pressing Backspace": "你可以使用 Backspace(倒退鍵) 來清除快捷鍵。",
|
||||
"Price check": "查詢價格",
|
||||
"Auto-hide Mode": "自動隱藏模式",
|
||||
"Open without auto-hide": "一般模式",
|
||||
"Overlay": "Overlay",
|
||||
"Open item on wiki": "開啟wiki頁面",
|
||||
"Map check": "檢查地圖",
|
||||
"Item info": "物品資訊",
|
||||
"Stash tab scrolling": "切換倉庫頁",
|
||||
"Delve grid": "礦坑網格"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -214,6 +214,9 @@ export default defineComponent({
|
||||
"Loading leagues...": "Загрузка лиг...",
|
||||
"Failed to load leagues": "Не удалось загрузить лиги",
|
||||
"Show price prediction": "Показывать приблизительную цену"
|
||||
},
|
||||
"cmn-Hant": {
|
||||
"League": "聯盟"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
Reference in New Issue
Block a user