add zh_TW (#589)

Co-authored-by: Alexander Drozdov <snosme@gmail.com>
This commit is contained in:
HRay
2022-05-08 23:14:38 +08:00
committed by GitHub
parent b6a47e7a61
commit 5297a50d71
29 changed files with 10421 additions and 86 deletions

View File

@@ -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: [

View File

@@ -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
}

View File

@@ -94,4 +94,7 @@ export const LANGUAGE_DETECTOR = [{
}, {
lang: 'ko',
firstLine: '아이템 종류: '
}, {
lang: 'cmn-Hant',
firstLine: '物品種類: '
}]

View 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": "支持開發"
}

View 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>.+)$/
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">

View File

@@ -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 = {

View File

@@ -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'
}
}

View File

@@ -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'))

View File

@@ -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

View File

@@ -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>.+)?$/
}

View File

@@ -74,6 +74,9 @@ export default defineComponent({
"ru": {
"Item has no modifiers.": "На предмете нету модов.",
"has_outdated": "Перевод некоторых свойств был изменен. Проверьте и обновите опасные моды карт в настройках. (Это сообщение будет скрыто, как только вы удалите все устаревшие переводы)"
},
"cmn-Hant" :{
"has_outdataed" :"部份詞綴描述已變更,請檢查並更新地圖的危險詞綴。(當你刪除將所有舊版詞綴,此訊息會隱藏)"
}
}
</i18n>

View File

@@ -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}`)
}

View File

@@ -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)

View File

@@ -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) ||

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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') {

View File

@@ -10,6 +10,7 @@ export interface FilterPreset {
interface SearchFilter {
name?: string
nameTrade?: string
baseType?: string
baseTypeTrade?: string
category?: ItemCategory

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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>

View File

@@ -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>

View File

@@ -214,6 +214,9 @@ export default defineComponent({
"Loading leagues...": "Загрузка лиг...",
"Failed to load leagues": "Не удалось загрузить лиги",
"Show price prediction": "Показывать приблизительную цену"
},
"cmn-Hant": {
"League": "聯盟"
}
}
</i18n>