diff --git a/wowup-electron/buildspec_windows.yml b/wowup-electron/buildspec.yml similarity index 50% rename from wowup-electron/buildspec_windows.yml rename to wowup-electron/buildspec.yml index d66d69d8..e6562894 100644 --- a/wowup-electron/buildspec_windows.yml +++ b/wowup-electron/buildspec.yml @@ -5,4 +5,8 @@ phases: commands: - echo Install phase... - cd wowup-electron - - npm i \ No newline at end of file + - npm i + build: + commands: + - echo Build phase... + - npm run electron:publish:never \ No newline at end of file diff --git a/wowup-electron/package.json b/wowup-electron/package.json index 92882032..afd7e956 100644 --- a/wowup-electron/package.json +++ b/wowup-electron/package.json @@ -1,7 +1,7 @@ { "name": "wowup", "productName": "WowUp", - "version": "2.0.0-beta.18", + "version": "2.0.0-beta.19", "description": "Word of Warcraft addon updater", "homepage": "https://wowup.io", "author": { diff --git a/wowup-electron/src/app/addon-providers/addon-provider.ts b/wowup-electron/src/app/addon-providers/addon-provider.ts index b8f60d22..5ed869f7 100644 --- a/wowup-electron/src/app/addon-providers/addon-provider.ts +++ b/wowup-electron/src/app/addon-providers/addon-provider.ts @@ -26,6 +26,7 @@ export interface AddonProvider { getById(addonId: string, clientType: WowClientType): Observable; isValidAddonUri(addonUri: URL): boolean; + isValidAddonId(addonId: string): boolean; onPostInstall(addon: Addon): void; diff --git a/wowup-electron/src/app/addon-providers/curse-addon-provider.ts b/wowup-electron/src/app/addon-providers/curse-addon-provider.ts index 5790a335..6c197ccc 100644 --- a/wowup-electron/src/app/addon-providers/curse-addon-provider.ts +++ b/wowup-electron/src/app/addon-providers/curse-addon-provider.ts @@ -342,6 +342,10 @@ export class CurseAddonProvider implements AddonProvider { return addonUri.host && addonUri.host.endsWith("curseforge.com") && addonUri.pathname.startsWith("/wow/addons"); } + isValidAddonId(addonId: string): boolean { + return !!addonId && !isNaN(parseInt(addonId, 10)); + } + onPostInstall(addon: Addon): void { throw new Error("Method not implemented."); } diff --git a/wowup-electron/src/app/addon-providers/github-addon-provider.ts b/wowup-electron/src/app/addon-providers/github-addon-provider.ts index 673492d8..503972d2 100644 --- a/wowup-electron/src/app/addon-providers/github-addon-provider.ts +++ b/wowup-electron/src/app/addon-providers/github-addon-provider.ts @@ -148,6 +148,10 @@ export class GitHubAddonProvider implements AddonProvider { return addonUri.host && addonUri.host.endsWith("github.com"); } + public isValidAddonId(addonId: string): boolean { + return addonId.indexOf("/") !== -1; + } + public onPostInstall(addon: Addon): void {} public async scan( diff --git a/wowup-electron/src/app/addon-providers/tukui-addon-provider.ts b/wowup-electron/src/app/addon-providers/tukui-addon-provider.ts index d675b6e3..1e0fdb70 100644 --- a/wowup-electron/src/app/addon-providers/tukui-addon-provider.ts +++ b/wowup-electron/src/app/addon-providers/tukui-addon-provider.ts @@ -108,6 +108,10 @@ export class TukUiAddonProvider implements AddonProvider { return false; } + isValidAddonId(addonId: string): boolean { + return !!addonId && !isNaN(parseInt(addonId, 10)); + } + onPostInstall(addon: Addon): void {} async scan( diff --git a/wowup-electron/src/app/addon-providers/wow-interface-addon-provider.ts b/wowup-electron/src/app/addon-providers/wow-interface-addon-provider.ts index 11c7b52d..36ab67b4 100644 --- a/wowup-electron/src/app/addon-providers/wow-interface-addon-provider.ts +++ b/wowup-electron/src/app/addon-providers/wow-interface-addon-provider.ts @@ -88,17 +88,21 @@ export class WowInterfaceAddonProvider implements AddonProvider { throw new Error("Method not implemented."); } - getById(addonId: string, clientType: WowClientType): Observable { + public getById(addonId: string, clientType: WowClientType): Observable { return from(this._circuitBreaker.fire(addonId)).pipe( map((result) => (result ? this.toAddonSearchResult(result, "") : undefined)) ); } - isValidAddonUri(addonUri: URL): boolean { + public isValidAddonUri(addonUri: URL): boolean { return addonUri.host && addonUri.host.endsWith("wowinterface.com"); } - onPostInstall(addon: Addon): void { + public isValidAddonId(addonId: string): boolean { + return !!addonId && !isNaN(parseInt(addonId, 10)); + } + + public onPostInstall(addon: Addon): void { throw new Error("Method not implemented."); } diff --git a/wowup-electron/src/app/addon-providers/wowup-addon-provider.ts b/wowup-electron/src/app/addon-providers/wowup-addon-provider.ts index e98e3275..8b91d74a 100644 --- a/wowup-electron/src/app/addon-providers/wowup-addon-provider.ts +++ b/wowup-electron/src/app/addon-providers/wowup-addon-provider.ts @@ -67,6 +67,10 @@ export class WowUpAddonProvider implements AddonProvider { return false; } + isValidAddonId(addonId: string): boolean { + return true; + } + onPostInstall(addon: Addon): void { throw new Error("Method not implemented."); } diff --git a/wowup-electron/src/app/components/my-addons-addon-cell/my-addons-addon-cell.component.html b/wowup-electron/src/app/components/my-addons-addon-cell/my-addons-addon-cell.component.html index eb51fd4c..578bf485 100644 --- a/wowup-electron/src/app/components/my-addons-addon-cell/my-addons-addon-cell.component.html +++ b/wowup-electron/src/app/components/my-addons-addon-cell/my-addons-addon-cell.component.html @@ -35,7 +35,8 @@
- +
diff --git a/wowup-electron/src/app/components/wow-client-options/wow-client-options.component.html b/wowup-electron/src/app/components/wow-client-options/wow-client-options.component.html index df505371..7d25f1fe 100644 --- a/wowup-electron/src/app/components/wow-client-options/wow-client-options.component.html +++ b/wowup-electron/src/app/components/wow-client-options/wow-client-options.component.html @@ -6,6 +6,10 @@ "PAGES.OPTIONS.WOW.CLIENT_TYPE_PATH_LABEL" | translate: { clientTypeName: (clientTypeName | translate) } }} + {{ "PAGES.OPTIONS.WOW.CLIENT_TYPE_INPUT_HINT" diff --git a/wowup-electron/src/app/components/wow-client-options/wow-client-options.component.ts b/wowup-electron/src/app/components/wow-client-options/wow-client-options.component.ts index 9d192c01..8370ee0d 100644 --- a/wowup-electron/src/app/components/wow-client-options/wow-client-options.component.ts +++ b/wowup-electron/src/app/components/wow-client-options/wow-client-options.component.ts @@ -2,9 +2,12 @@ import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from "@angular import { MatDialog } from "@angular/material/dialog"; import { MatSelectChange } from "@angular/material/select"; import { MatSlideToggleChange } from "@angular/material/slide-toggle"; +import { TranslateService } from "@ngx-translate/core"; import * as _ from "lodash"; +import { map } from "lodash"; import * as path from "path"; -import { Subscription } from "rxjs"; +import { from, Subscription } from "rxjs"; +import { switchMap } from "rxjs/operators"; import { WowClientType } from "../../models/warcraft/wow-client-type"; import { AddonChannelType } from "../../models/wowup/addon-channel-type"; import { ElectronService } from "../../services"; @@ -12,6 +15,7 @@ import { WarcraftService } from "../../services/warcraft/warcraft.service"; import { WowUpService } from "../../services/wowup/wowup.service"; import { getEnumList, getEnumName } from "../../utils/enum.utils"; import { AlertDialogComponent } from "../alert-dialog/alert-dialog.component"; +import { ConfirmDialogComponent } from "../confirm-dialog/confirm-dialog.component"; @Component({ selector: "app-wow-client-options", @@ -40,7 +44,8 @@ export class WowClientOptionsComponent implements OnInit, OnDestroy { private _electronService: ElectronService, private _warcraftService: WarcraftService, private _wowupService: WowUpService, - private _cdRef: ChangeDetectorRef + private _cdRef: ChangeDetectorRef, + private _translateService: TranslateService ) { this.addonChannelInfos = this.getAddonChannelInfos(); @@ -75,6 +80,32 @@ export class WowClientOptionsComponent implements OnInit, OnDestroy { this._wowupService.setDefaultAutoUpdate(this.clientType, evt.checked); } + public async clearInstallPath() { + const dialogRef = this._dialog.open(ConfirmDialogComponent, { + data: { + title: this._translateService.instant("PAGES.OPTIONS.WOW.CLEAR_INSTALL_LOCATION_DIALOG.TITLE"), + message: this._translateService.instant("PAGES.OPTIONS.WOW.CLEAR_INSTALL_LOCATION_DIALOG.MESSAGE", { + clientName: this._translateService.instant(this.clientTypeName), + }), + }, + }); + + const result = await dialogRef.afterClosed().toPromise(); + + if (!result) { + return; + } + + try { + await this._warcraftService.removeWowFolderPath(this.clientType).toPromise(); + this.clientLocation = ""; + this._cdRef.detectChanges(); + console.debug("Remove client location complete"); + } catch (e) { + console.error("Failed to remove location", e); + } + } + async onSelectClientPath() { const selectedPath = await this.selectWowClientPath(this.clientType); if (selectedPath) { diff --git a/wowup-electron/src/app/services/addons/addon.service.ts b/wowup-electron/src/app/services/addons/addon.service.ts index 4a7373c3..a8c9e047 100644 --- a/wowup-electron/src/app/services/addons/addon.service.ts +++ b/wowup-electron/src/app/services/addons/addon.service.ts @@ -3,12 +3,17 @@ import { AddonDependency } from "app/models/wowup/addon-dependency"; import { AddonDependencyType } from "app/models/wowup/addon-dependency-type"; import { AddonSearchResultDependency } from "app/models/wowup/addon-search-result-dependency"; import { Toc } from "app/models/wowup/toc"; -import { ADDON_PROVIDER_CURSEFORGE, ADDON_PROVIDER_TUKUI, ADDON_PROVIDER_WOWINTERFACE } from "common/constants"; +import { + ADDON_PROVIDER_CURSEFORGE, + ADDON_PROVIDER_TUKUI, + ADDON_PROVIDER_WOWINTERFACE, + ERROR_ADDON_ALREADY_INSTALLED, +} from "common/constants"; import * as fs from "fs"; import * as _ from "lodash"; import * as path from "path"; import { forkJoin, from, Observable, Subject } from "rxjs"; -import { map, mergeMap } from "rxjs/operators"; +import { filter, first, map, mergeMap, switchMap } from "rxjs/operators"; import * as slug from "slug"; import { v4 as uuidv4 } from "uuid"; import { AddonProvider } from "../../addon-providers/addon-provider"; @@ -69,6 +74,16 @@ export class AddonService { this._installQueue.pipe(mergeMap((item) => from(this.processInstallQueue(item)), 3)).subscribe((addonName) => { console.log("Install complete", addonName); }); + + // Attempt to remove addons for clients that were lost + this._warcraftService.installedClientTypes$ + .pipe( + filter((clientTypes) => !!clientTypes), + switchMap((clientTypes) => from(this.reconcileOrphanAddons(clientTypes))) + ) + .subscribe(() => { + console.debug("reconcileOrphanAddons complete"); + }); } public saveAddon(addon: Addon) { @@ -217,7 +232,7 @@ export class AddonService { addonId, onUpdate, completion, - originalAddon: originalAddon ? { ...originalAddon } : undefined + originalAddon: originalAddon ? { ...originalAddon } : undefined, }); return promise; @@ -306,8 +321,9 @@ export class AddonService { this._addonStorage.set(addon.id, addon); - const actionLabel = `${getEnumName(WowClientType, addon.clientType)}|${addon.providerName}|${addon.externalId}|${addon.name - }`; + const actionLabel = `${getEnumName(WowClientType, addon.clientType)}|${addon.providerName}|${addon.externalId}|${ + addon.name + }`; this._analyticsService.trackAction("install-addon", { clientType: getEnumName(WowClientType, addon.clientType), provider: addon.providerName, @@ -486,13 +502,15 @@ export class AddonService { .filter((f) => !!f); } - public async removeAddon(addon: Addon, removeDependencies: boolean = false) { + public async removeAddon(addon: Addon, removeDependencies: boolean = false, removeDirectories: boolean = true) { const installedDirectories = addon.installedFolders?.split(",") ?? []; - const addonFolderPath = this._warcraftService.getAddonFolderPath(addon.clientType); - for (let directory of installedDirectories) { - const addonDirectory = path.join(addonFolderPath, directory); - await this._fileService.remove(addonDirectory); + + if (removeDirectories) { + for (let directory of installedDirectories) { + const addonDirectory = path.join(addonFolderPath, directory); + await this._fileService.remove(addonDirectory); + } } this._addonStorage.remove(addon); @@ -647,44 +665,51 @@ export class AddonService { } const externalIds: AddonExternalId[] = []; - if (toc.wowInterfaceId) { - externalIds.push({ - id: toc.wowInterfaceId, - providerName: ADDON_PROVIDER_WOWINTERFACE, - }); - } - - if (toc.tukUiProjectId) { - externalIds.push({ - id: toc.tukUiProjectId, - providerName: ADDON_PROVIDER_TUKUI, - }); - } - - if (toc.curseProjectId) { - externalIds.push({ - id: toc.curseProjectId, - providerName: ADDON_PROVIDER_CURSEFORGE, - }); - } + this.insertExternalId(externalIds, ADDON_PROVIDER_WOWINTERFACE, toc.wowInterfaceId); + this.insertExternalId(externalIds, ADDON_PROVIDER_TUKUI, toc.tukUiProjectId); + this.insertExternalId(externalIds, ADDON_PROVIDER_CURSEFORGE, toc.curseProjectId); //If the addon does not include the current external id add it if (!this.containsOwnExternalId(addon, externalIds)) { - externalIds.push({ - id: addon.externalId, - providerName: addon.providerName - }); + this.insertExternalId(externalIds, addon.providerName, addon.externalId); } addon.externalIds = externalIds; } + public insertExternalId(externalIds: AddonExternalId[], providerName: string, addonId?: string) { + if (!addonId) { + return; + } + + const exists = + _.findIndex(externalIds, (extId) => extId.id === addonId && extId.providerName === providerName) !== -1; + + if (exists) { + console.debug(`External id exists ${providerName}|${addonId}`); + return; + } + + if (this.getProvider(providerName).isValidAddonId(addonId)) { + externalIds.push({ + id: addonId, + providerName: providerName, + }); + } else { + console.debug(`Invalid provider id ${providerName}|${addonId}`); + } + } + public async setProvider(addon: Addon, externalId: string, providerName: string, clientType: WowClientType) { const provider = this.getProvider(providerName); if (!provider) { throw new Error(`Provider not found: ${providerName}`); } + if (this.isInstalled(externalId, clientType)) { + throw new Error(ERROR_ADDON_ALREADY_INSTALLED); + } + const externalAddon = await this.getAddon(externalId, providerName, clientType).toPromise(); if (!externalAddon) { throw new Error(`External addon not found: ${providerName}|${externalId}`); @@ -693,7 +718,21 @@ export class AddonService { this.saveAddon(externalAddon); await this.installAddon(externalAddon.id, undefined, addon); - await this.removeAddon(addon, false); + await this.removeAddon(addon, false, false); + } + + public async reconcileOrphanAddons(installedClientTypes: WowClientType[]) { + console.debug("reconcileOrphanAddons", installedClientTypes); + const clientTypes = this._warcraftService.getAllClientTypes(); + const unusedClients = _.difference(clientTypes, installedClientTypes); + console.debug("unusedClients", unusedClients); + + for (let clientType of unusedClients) { + const addons = this._addonStorage.getAllForClientType(clientType); + for (let addon of addons) { + await this.removeAddon(addon, false, false); + } + } } public reconcileExternalIds(newAddon: Addon, oldAddon: Addon) { @@ -701,14 +740,21 @@ export class AddonService { return; } - oldAddon.externalIds.forEach(oldExtId => { - const match = newAddon.externalIds.find(newExtId => newExtId.id === oldExtId.id && newExtId.providerName === oldExtId.providerName); + // Ensure all previously existing external ids are brought along during the swap + // some addons are not always the same between providers ;) + oldAddon.externalIds.forEach((oldExtId) => { + const match = newAddon.externalIds.find( + (newExtId) => newExtId.id === oldExtId.id && newExtId.providerName === oldExtId.providerName + ); if (match) { return; } console.log(`Reconciling external id: ${oldExtId.providerName}|${oldExtId.id}`); newAddon.externalIds.push({ ...oldExtId }); - }) + }); + + // Remove external ids that are not valid that we may have saved previously + _.remove(newAddon.externalIds, (extId) => !this.getProvider(extId.providerName).isValidAddonId(extId.id)); this.saveAddon(newAddon); } @@ -730,9 +776,7 @@ export class AddonService { } public async backfillAddons() { - const clientTypes = getEnumList(WowClientType).filter( - (clientType) => clientType !== WowClientType.None - ); + const clientTypes = this._warcraftService.getAllClientTypes(); for (let clientType of clientTypes) { const addons = this._addonStorage.getAllForClientType(clientType); @@ -761,7 +805,7 @@ export class AddonService { public containsOwnExternalId(addon: Addon, array?: AddonExternalId[]): boolean { const arr = array || addon.externalIds; - const result = arr && !!arr.find(ext => ext.id === addon.externalId && ext.providerName === addon.providerName); + const result = arr && !!arr.find((ext) => ext.id === addon.externalId && ext.providerName === addon.providerName); return result; } @@ -819,6 +863,7 @@ export class AddonService { summary: searchResult.summary, screenshotUrls: searchResult.screenshotUrls, dependencies, + externalChannel: getEnumName(AddonChannelType, latestFile.channelType), }; } diff --git a/wowup-electron/src/app/services/session/session.service.ts b/wowup-electron/src/app/services/session/session.service.ts index 32f1f79d..889126c3 100644 --- a/wowup-electron/src/app/services/session/session.service.ts +++ b/wowup-electron/src/app/services/session/session.service.ts @@ -1,6 +1,7 @@ import { Injectable } from "@angular/core"; import { BehaviorSubject } from "rxjs"; import { filter, first, map } from "rxjs/operators"; +import { first as ldFirst } from "lodash"; import { WowClientType } from "../../models/warcraft/wow-client-type"; import { WarcraftService } from "../warcraft/warcraft.service"; import { WowUpService } from "../wowup/wowup.service"; @@ -23,6 +24,22 @@ export class SessionService { constructor(private _warcraftService: WarcraftService, private _wowUpService: WowUpService) { this.loadInitialClientType().pipe(first()).subscribe(); + + this._warcraftService.installedClientTypes$ + .pipe(filter((clientTypes) => !!clientTypes)) + .subscribe((clientTypes) => this.onInstalledClientsChange(clientTypes)); + } + + public onInstalledClientsChange(installedClientTypes: WowClientType[]) { + if (!installedClientTypes.length) { + this._selectedClientTypeSrc.next(WowClientType.None); + } + + if (installedClientTypes.indexOf(this.selectedClientType) !== -1) { + return; + } + + this.selectedClientType = ldFirst(installedClientTypes); } public autoUpdateComplete() { diff --git a/wowup-electron/src/app/services/storage/preference-storage.service.ts b/wowup-electron/src/app/services/storage/preference-storage.service.ts index bd1ffcf0..5593daf9 100644 --- a/wowup-electron/src/app/services/storage/preference-storage.service.ts +++ b/wowup-electron/src/app/services/storage/preference-storage.service.ts @@ -36,4 +36,8 @@ export class PreferenceStorageService { public getObject(key: string): T | undefined { return this._store.get(key, undefined) as T; } + + public remove(key: string): void { + this._store.delete(key); + } } diff --git a/wowup-electron/src/app/services/warcraft/warcraft.service.ts b/wowup-electron/src/app/services/warcraft/warcraft.service.ts index dcb640b4..51a8e3ea 100644 --- a/wowup-electron/src/app/services/warcraft/warcraft.service.ts +++ b/wowup-electron/src/app/services/warcraft/warcraft.service.ts @@ -42,6 +42,9 @@ export class WarcraftService { private readonly _impl: WarcraftServiceImpl; private readonly _productsSrc = new BehaviorSubject([]); private readonly _installedClientTypesSrc = new BehaviorSubject(undefined); + private readonly _allClientTypes = getEnumList(WowClientType).filter( + (clientType) => clientType !== WowClientType.None + ); private _productDbPath = ""; @@ -108,12 +111,14 @@ export class WarcraftService { return path.join(fullClientPath, INTERFACE_FOLDER_NAME, ADDON_FOLDER_NAME); } + public getAllClientTypes() { + return [...this._allClientTypes]; + } + public async getWowClientTypes() { const clients: WowClientType[] = []; - const clientTypes = getEnumList(WowClientType).filter( - (clientType) => clientType !== WowClientType.None - ); + const clientTypes = this.getAllClientTypes(); for (let clientType of clientTypes) { const clientLocation = this.getClientLocation(clientType); @@ -142,9 +147,7 @@ export class WarcraftService { const installedProducts = this.decodeProducts(this._productDbPath); this._productsSrc.next(installedProducts); - const clientTypes = getEnumList(WowClientType).filter( - (clientType) => clientType !== WowClientType.None - ); + const clientTypes = this.getAllClientTypes(); for (const clientType of clientTypes) { const clientLocation = this.getClientLocation(clientType); @@ -169,6 +172,8 @@ export class WarcraftService { this.setClientLocation(clientType, productLocation); } + this.broadcastInstalledClients().subscribe(); + return installedProducts; } @@ -235,6 +240,13 @@ export class WarcraftService { return this._preferenceStorageService.set(clientLocationKey, clientPath); } + public removeWowFolderPath(clientType: WowClientType) { + const clientLocationKey = this.getClientLocationKey(clientType); + this._preferenceStorageService.remove(clientLocationKey); + + return this.broadcastInstalledClients(); + } + public setWowFolderPath(clientType: WowClientType, folderPath: string): boolean { const relativePath = this.getClientRelativePath(clientType, folderPath); @@ -337,6 +349,12 @@ export class WarcraftService { } } + private broadcastInstalledClients() { + return from(this.getWowClientTypes()).pipe( + map((wowClientTypes) => this._installedClientTypesSrc.next(wowClientTypes)) + ); + } + private decodeProducts(productDbPath: string) { if (this._electronService.isLinux) { return []; diff --git a/wowup-electron/src/assets/changelog.json b/wowup-electron/src/assets/changelog.json index ea618b02..71a70a34 100644 --- a/wowup-electron/src/assets/changelog.json +++ b/wowup-electron/src/assets/changelog.json @@ -1,5 +1,13 @@ { "ChangeLogs": [ + { + "Version": "2.0.0-beta.19", + "changes": [ + "Add the ability to clear an installation path", + "Add the ability to have addons removed for installations that are missing", + "Fix some issues related to switching providers" + ] + }, { "Version": "2.0.0-beta.18", "changes": [ @@ -9,9 +17,7 @@ }, { "Version": "2.0.0-beta.17", - "changes": [ - "Bug fixes" - ] + "changes": ["Bug fixes"] }, { "Version": "2.0.0-beta.16", @@ -33,10 +39,7 @@ }, { "Version": "2.0.0-beta.15", - "changes": [ - "Fix an issue where light/dark themes could overlap", - "Fix an issue with a nested translate call" - ] + "changes": ["Fix an issue where light/dark themes could overlap", "Fix an issue with a nested translate call"] }, { "Version": "2.0.0-beta.14", diff --git a/wowup-electron/src/assets/i18n/de.json b/wowup-electron/src/assets/i18n/de.json index 6ca18978..94ef7b86 100644 --- a/wowup-electron/src/assets/i18n/de.json +++ b/wowup-electron/src/assets/i18n/de.json @@ -10,8 +10,8 @@ "THEME": { "ALLIANCE": "Allianz", "DEFAULT": "Standard", - "GROUP_DARK": "Dark", - "GROUP_LIGHT": "Light", + "GROUP_DARK": "Dunkel", + "GROUP_LIGHT": "Hell", "HORDE": "Horde" }, "WOWUP_UPDATE": { @@ -68,13 +68,13 @@ "e+0": "{count}", "e+1": "{count}", "e+2": "{count}", - "e+3": "{count} thousand", - "e+4": "{count} thousand", - "e+5": "{count} thousand", - "e+6": "{count} million", - "e+7": "{count} million", - "e+8": "{count} million", - "e+9": "{count} billion" + "e+3": "{count} Tausend", + "e+4": "{count} Tausend", + "e+5": "{count} Tausend", + "e+6": "{count} Millionen", + "e+7": "{count} Millionen", + "e+8": "{count} Millionen", + "e+9": "{count} Milliarden" }, "ENUM": { "ADDON_CHANNEL_TYPE": { @@ -84,7 +84,7 @@ } }, "ERRORS": { - "CHANGE_PROVIDER_ERROR": "Failed to change provider for {addonName} to {providerName}" + "CHANGE_PROVIDER_ERROR": "Anbieterwechsel von {addonName} nach {providerName} fehlgeschlagen" }, "PROGRESS_SPINNER": { "LOADING": "Laden..." @@ -168,15 +168,15 @@ "BETA_ADDON_CHANNEL": "Beta", "CHANNEL_SUBMENU_TITLE": "Kanal", "IGNORE_ADDON_BUTTON": "Ignorieren", - "PROVIDER_SUBMENU_TITLE": "Providers", + "PROVIDER_SUBMENU_TITLE": "Anbieter", "REINSTALL_ADDON_BUTTON": "Neu installieren", "REMOVE_ADDON_BUTTON": "Entfernen", "SHOW_FOLDER": "Dateiordner anzeigen", "STABLE_ADDON_CHANNEL": "Stabil" }, "CHANGE_ADDON_PROVIDER_CONFIRMATION": { - "MESSAGE": "Do you want to change the addon provider for {addonName} to {providerName}? This operation will uninstall your existing addon and replace it with a copy from the new provider.", - "TITLE": "Change Addon Provider?" + "MESSAGE": "Möchtest du den Addon Anbieter für {addonName} auf {providerName} festlegen? Dies wird das aktuelle Addon deinstallieren und durch eine Version vom neuen Anbieter ersetzen.", + "TITLE": "Addon Anbieter wechsel?" }, "CHECK_UPDATES_BUTTON": "Updates prüfen", "CHECK_UPDATES_BUTTON_TOOLTIP": "Nach neuen Addon-Updates suchen", @@ -185,6 +185,7 @@ "TITLE": "Spalten anzeigen" }, "FILTER_LABEL": "Filter", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "{count} {count, plural, =1{Addon} other{Addons}}", "JOIN_DISCORD": "Schreibe mit uns auf Discord", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "Neu installierte Addons werden standardmäßig auf Auto-Update gesetzt", "AUTO_UPDATE_LABEL": "Automatisch aktualisieren", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "Der Order, der den {clientTypeName} Clientorder \"{clientFolderName}\" enthält", "CLIENT_TYPE_PATH_LABEL": "{clientTypeName} Pfad", "DEFAULT_ADDON_CHANNEL_LABEL": "Standard-Addon-Kanal", diff --git a/wowup-electron/src/assets/i18n/en.json b/wowup-electron/src/assets/i18n/en.json index 960b61da..39a58f40 100644 --- a/wowup-electron/src/assets/i18n/en.json +++ b/wowup-electron/src/assets/i18n/en.json @@ -185,6 +185,7 @@ "TITLE": "Show Columns" }, "FILTER_LABEL": "Filter", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "{count} {count, plural, =1{addon} other{addons}}", "JOIN_DISCORD": "Chat with us on Discord", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "Newly installed addons will be set to auto update by default", "AUTO_UPDATE_LABEL": "Auto Update", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "The folder that contains the {clientTypeName} client folder \"{clientFolderName}\"", "CLIENT_TYPE_PATH_LABEL": "{clientTypeName} path", "DEFAULT_ADDON_CHANNEL_LABEL": "Default Addon Channel", diff --git a/wowup-electron/src/assets/i18n/es.json b/wowup-electron/src/assets/i18n/es.json index f340f3dc..1fa48b71 100644 --- a/wowup-electron/src/assets/i18n/es.json +++ b/wowup-electron/src/assets/i18n/es.json @@ -185,6 +185,7 @@ "TITLE": "Mostrar Columna" }, "FILTER_LABEL": "Filtro", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "{count} {count, plural, =1{addon} other{addons}}", "JOIN_DISCORD": "Charle con nosotros en Discord", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "Los addons instalados después de activar esta opción se configurarán para actualizarse automáticamente de forma predeterminada", "AUTO_UPDATE_LABEL": "Actualización automática", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "La carpeta que contiene la versión {clientTypeName} del cliente de World of Warcraft \"{clientFolderName}\"", "CLIENT_TYPE_PATH_LABEL": "Ruta de {clientTypeName}", "DEFAULT_ADDON_CHANNEL_LABEL": "Canal de Addons Predeterminado", diff --git a/wowup-electron/src/assets/i18n/fr.json b/wowup-electron/src/assets/i18n/fr.json index 13286ea7..2b20290f 100644 --- a/wowup-electron/src/assets/i18n/fr.json +++ b/wowup-electron/src/assets/i18n/fr.json @@ -10,8 +10,8 @@ "THEME": { "ALLIANCE": "Alliance", "DEFAULT": "Défaut", - "GROUP_DARK": "Dark", - "GROUP_LIGHT": "Light", + "GROUP_DARK": "Sombre", + "GROUP_LIGHT": "Clair", "HORDE": "Horde" }, "WOWUP_UPDATE": { @@ -48,9 +48,9 @@ "CLIENT_TYPES": { "BETA": "Beta", "CLASSIC": "Classic", - "CLASSICPTR": "Classic PTR", + "CLASSICPTR": "PTR Classic", "RETAIL": "Retail", - "RETAILPTR": "Retail PTR" + "RETAILPTR": "PTR Retail" }, "DATES": { "DATETIME_SHORT": "{d, date, short} {d, time, short}", @@ -68,13 +68,13 @@ "e+0": "{count}", "e+1": "{count}", "e+2": "{count}", - "e+3": "{count} thousand", - "e+4": "{count} thousand", - "e+5": "{count} thousand", - "e+6": "{count} million", - "e+7": "{count} million", - "e+8": "{count} million", - "e+9": "{count} billion" + "e+3": "{count} {count, plural, one{millier} other{{count} milliers}}", + "e+4": "{count} milliers", + "e+5": "{count} milliers", + "e+6": "{count} {count, plural, one{million} other{{count} millions}} ", + "e+7": "{count} millions", + "e+8": "{count} millions", + "e+9": "{count} {count, plural, one{milliard} other{{count} milliards}} " }, "ENUM": { "ADDON_CHANNEL_TYPE": { @@ -84,7 +84,7 @@ } }, "ERRORS": { - "CHANGE_PROVIDER_ERROR": "Failed to change provider for {addonName} to {providerName}" + "CHANGE_PROVIDER_ERROR": "Impossible de changer le fournisseur {providerName} pour l´addon {addonName}" }, "PROGRESS_SPINNER": { "LOADING": "Chargement..." @@ -101,7 +101,7 @@ "VIEW_ON_PROVIDER_PREFIX": "Voir sur" }, "ALERT": { - "ERROR_TITLE": "Error", + "ERROR_TITLE": "Erreur", "POSITIVE_BUTTON": "Ok" }, "CONFIRM": { @@ -168,15 +168,15 @@ "BETA_ADDON_CHANNEL": "Bêta", "CHANNEL_SUBMENU_TITLE": "Canal", "IGNORE_ADDON_BUTTON": "Ignorer", - "PROVIDER_SUBMENU_TITLE": "Providers", + "PROVIDER_SUBMENU_TITLE": "Fournisseurs", "REINSTALL_ADDON_BUTTON": "Réinstaller", "REMOVE_ADDON_BUTTON": "Désinstaller", "SHOW_FOLDER": "Montrer le dossier", "STABLE_ADDON_CHANNEL": "Stable" }, "CHANGE_ADDON_PROVIDER_CONFIRMATION": { - "MESSAGE": "Do you want to change the addon provider for {addonName} to {providerName}? This operation will uninstall your existing addon and replace it with a copy from the new provider.", - "TITLE": "Change Addon Provider?" + "MESSAGE": "Souhaitez-vous changer le fournisseur d´addons pour {addonName} par {providerName}? Cette opération désinstallera l´addon existant et le remplacera par une copie du nouveau fournisseur.", + "TITLE": "Changer de fournisseur d´addon" }, "CHECK_UPDATES_BUTTON": "Vérifier les mises à jour", "CHECK_UPDATES_BUTTON_TOOLTIP": "Vérifier les dernières mises à jour des modules complémentaires", @@ -185,6 +185,7 @@ "TITLE": "Afficher les colonnes" }, "FILTER_LABEL": "Filter", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "{count} {count, plural, =1{addon} other{addons}}", "JOIN_DISCORD": "Discutez avec nous sur Discord", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "Les addons nouvellement installés seront mises à jour automatiquement par défaut", "AUTO_UPDATE_LABEL": "Mise à jour automatique", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "Ce dossier contient le client {clientTypeName} avec le dossier \"{clientFolderName}\"", "CLIENT_TYPE_PATH_LABEL": "Chemin de {clientTypeName}", "DEFAULT_ADDON_CHANNEL_LABEL": "Canal d'extension par défaut", diff --git a/wowup-electron/src/assets/i18n/it.json b/wowup-electron/src/assets/i18n/it.json index 83deac83..0c75f029 100644 --- a/wowup-electron/src/assets/i18n/it.json +++ b/wowup-electron/src/assets/i18n/it.json @@ -1,7 +1,7 @@ { "APP": { "AUTO_UPDATE_NOTIFICATION_BODY": "Automaticamente {count, plural, =1{aggiornato} other{aggiornati}} {count} {count, plural, =1{addon} other{addons}}.", - "AUTO_UPDATE_NOTIFICATION_TITLE": "Aggiornamenti automatici", + "AUTO_UPDATE_NOTIFICATION_TITLE": "Aggiornamenti Automatici", "SYSTEM_TRAY": { "CHECK_UPDATE": "Controlla Aggiornamenti...", "QUIT_ACTION": "Chiudi", @@ -10,21 +10,21 @@ "THEME": { "ALLIANCE": "Alleanza", "DEFAULT": "Default", - "GROUP_DARK": "Dark", - "GROUP_LIGHT": "Light", + "GROUP_DARK": "Scuro", + "GROUP_LIGHT": "Chiaro", "HORDE": "Orda" }, "WOWUP_UPDATE": { "DOWNLOADED_TOOLTIP": "Installa l'aggiornamento di WowUp", "INSTALL_MESSAGE": "Vuoi riavviare WowUp per installare l'aggiornamento?", "INSTALL_TITLE": "Aggiornamento di Wowup pronto", - "NOT_AVAILABLE": "L'ultima versione di Wowup è già installata", + "NOT_AVAILABLE": "È già installata l'ultima versione di Wowup", "PORTABLE_DOWNLOAD_MESSAGE": "Vuoi scaricare manualmente l'ultima versione portatile?\n\nDovrai chiudere l'applicazione manualmente e sovrascrivere la nuova versione.", "PORTABLE_DOWNLOAD_TITLE": "Richiesto Download Manuale", "SNACKBAR_ACTION": "Aggiorna", "SNACKBAR_TEXT": "È disponibile una nuova versione di WowUp", - "TOOLTIP": "L'aggiornamento di WowUp è pronto per l'installazione", - "UPDATE_ERROR": "Errore nell'ottenere l'ultima versione di Wowup" + "TOOLTIP": "Aggiornamento di WowUp disponibile", + "UPDATE_ERROR": "Fallito nell'ottenere l'ultima versione di Wowup" } }, "COMMON": { @@ -57,8 +57,8 @@ "DAYS_AGO": "{count} {count, plural, one{giorno} other{giorni}} fa", "HOURS_AGO": "{count} {count, plural, one{ora} other{ore}} fa", "JUST_NOW": "Ora", - "MONTHS_AGO": "{count} {count, plural, one{month} other{months}} ago", - "YEARS_AGO": "{count} {count, plural, one{year} other{years}} ago", + "MONTHS_AGO": "{count} {count, plural, one{mese} other{mesi}} fa", + "YEARS_AGO": "{count} {count, plural, one{mese} other{mesi}} fa", "YESTERDAY": "Ieri" }, "DEPENDENCY": { @@ -68,13 +68,13 @@ "e+0": "{count}", "e+1": "{count}", "e+2": "{count}", - "e+3": "{count} thousand", - "e+4": "{count} thousand", - "e+5": "{count} thousand", - "e+6": "{count} million", - "e+7": "{count} million", - "e+8": "{count} million", - "e+9": "{count} billion" + "e+3": "{count} {count, plural, one{mille} other{{count} mila}}", + "e+4": "{count} {count, plural, one{mille} other{{count} mila}}", + "e+5": "{count} {count, plural, one{mille} other{{count} mila}}", + "e+6": "{count} {count, plural, one{milione} other{milioni}}", + "e+7": "{count} {count, plural, one{milione} other{milioni}}", + "e+8": "{count} {count, plural, one{milione} other{milioni}}", + "e+9": "{count} {count, plural, one{bilione} other{bilioni}}" }, "ENUM": { "ADDON_CHANNEL_TYPE": { @@ -84,7 +84,7 @@ } }, "ERRORS": { - "CHANGE_PROVIDER_ERROR": "Failed to change provider for {addonName} to {providerName}" + "CHANGE_PROVIDER_ERROR": "Fallito nel cambiare provider per {addonName} con {providerName}" }, "PROGRESS_SPINNER": { "LOADING": "Caricamento in corso..." @@ -101,7 +101,7 @@ "VIEW_ON_PROVIDER_PREFIX": "Visualizza su" }, "ALERT": { - "ERROR_TITLE": "Error", + "ERROR_TITLE": "Errore", "POSITIVE_BUTTON": "Ok" }, "CONFIRM": { @@ -113,7 +113,7 @@ "ADDON_URL_INPUT_PLACEHOLDER": "URL di esempio GitHub o WowInterface", "CLOSE_BUTTON": "Chiudi", "DESCRIPTION": "Se si desidera installare un addon direttamente da un URL incollarlo qui sotto per iniziare.", - "DOWNLOAD_COUNT": "{textCount} {count, plural, one{download} other{downloads}} on {provider}", + "DOWNLOAD_COUNT": "{textCount} {count, plural, one{download} other{downloads}} su {provider}", "ERROR": { "FAILED_TO_CONNECT": "Impossibile connettersi all'API, per favore riprovare più tardi.", "INSTALL_FAILED": "Qualcosa è andato storto nell'installazione dell'addon, per favore riprovare.\n\nSe questo messaggio continua ad apparire puoi chiederci aiuto su Discord, in #wow-support channel.", @@ -175,8 +175,8 @@ "STABLE_ADDON_CHANNEL": "Stabile" }, "CHANGE_ADDON_PROVIDER_CONFIRMATION": { - "MESSAGE": "Do you want to change the addon provider for {addonName} to {providerName}? This operation will uninstall your existing addon and replace it with a copy from the new provider.", - "TITLE": "Change Addon Provider?" + "MESSAGE": "Vuoi cambiare il provider dell'addon {addonName} con {providerName}? Questa operazione disinstallerà il tuo addon esistente e lo sostituirà con una copia dal nuovo provider.", + "TITLE": "Cambiare Provider dell'Addon??" }, "CHECK_UPDATES_BUTTON": "Controlla Aggiornamenti", "CHECK_UPDATES_BUTTON_TOOLTIP": "Controlla gli ultimi aggiornamenti degli addons", @@ -185,6 +185,7 @@ "TITLE": "Mostra Colonne" }, "FILTER_LABEL": "Filtra", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "{count} {count, plural, =1{addon} other{addons}}", "JOIN_DISCORD": "Contattaci su Discord", @@ -206,7 +207,7 @@ "ADDON_COLUMN_HEADER": "Addon", "ADDON_INSTALL_BUTTON": "Installa", "ADDON_UPDATE_BUTTON": "Aggiorna", - "AUTHOR_COLUMN_HEADER": "Autore", + "AUTHOR_COLUMN_HEADER": "Autore/i", "AUTO_UPDATE_ICON_TOOLTIP": "Aggiornamento automatico abilitato", "GAME_VERSION_COLUMN_HEADER": "Versione Del Gioco", "LATEST_VERSION_COLUMN_HEADER": "Ultima Versione", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "I nuovi addons installati saranno impostati di default per l'aggiornamento automatico ", "AUTO_UPDATE_LABEL": "Aggiornamento Automatico", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "La cartella che contiene {clientTypeName}: \"{clientFolderName}\"", "CLIENT_TYPE_PATH_LABEL": "{clientTypeName} path", "DEFAULT_ADDON_CHANNEL_LABEL": "Canale Addon Predefinito", diff --git a/wowup-electron/src/assets/i18n/ko.json b/wowup-electron/src/assets/i18n/ko.json index 803717bb..e2c0791a 100644 --- a/wowup-electron/src/assets/i18n/ko.json +++ b/wowup-electron/src/assets/i18n/ko.json @@ -185,6 +185,7 @@ "TITLE": "컬럼 보기" }, "FILTER_LABEL": "필터", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "{count}개의 애드온", "JOIN_DISCORD": "디스코드 입장", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "새로 설치되는 애드온의 자동업데이트 옵션을 활성화합니다.", "AUTO_UPDATE_LABEL": "자동 업데이트", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "\"{clientFolderName}\" 디렉토리를 포함하는 위치", "CLIENT_TYPE_PATH_LABEL": "{clientTypeName} 설치 위치", "DEFAULT_ADDON_CHANNEL_LABEL": "기본 애드온 채널", diff --git a/wowup-electron/src/assets/i18n/nb.json b/wowup-electron/src/assets/i18n/nb.json index b2d10064..422b5b61 100644 --- a/wowup-electron/src/assets/i18n/nb.json +++ b/wowup-electron/src/assets/i18n/nb.json @@ -185,6 +185,7 @@ "TITLE": "Vis Kolonner" }, "FILTER_LABEL": "Filter", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "{count} {count, plural, =1{utvidelse} other{utvidelser}}", "JOIN_DISCORD": "Chat med oss på Discord", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "Nye utvidelser du installerer vil bli satt til å oppdateres automatisk", "AUTO_UPDATE_LABEL": "Automatisk Oppdatering", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "Mappen som inneholder {clientTypeName} klientmappe \"{clientFolderName}\"", "CLIENT_TYPE_PATH_LABEL": "{clientTypeName} filbane", "DEFAULT_ADDON_CHANNEL_LABEL": "Standard kanal for utvidelser", diff --git a/wowup-electron/src/assets/i18n/pt.json b/wowup-electron/src/assets/i18n/pt.json index 5eedee37..e523a3fd 100644 --- a/wowup-electron/src/assets/i18n/pt.json +++ b/wowup-electron/src/assets/i18n/pt.json @@ -185,6 +185,7 @@ "TITLE": "Exibir Colunas" }, "FILTER_LABEL": "Filtrar", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "{count} {count, plural, =1{Addon} other{Addons}}", "JOIN_DISCORD": "Converse conosco no Discord", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "Addons recém-instalados serão definidos para atualizar automáticamente por padrão", "AUTO_UPDATE_LABEL": "Atualização Automática", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "A pasta \"{clientFolderName}\" que contém o {clientTypeName}", "CLIENT_TYPE_PATH_LABEL": "Pasta {clientTypeName}", "DEFAULT_ADDON_CHANNEL_LABEL": "Canal de Addon Padrão", diff --git a/wowup-electron/src/assets/i18n/ru.json b/wowup-electron/src/assets/i18n/ru.json index 852f9677..f2824605 100644 --- a/wowup-electron/src/assets/i18n/ru.json +++ b/wowup-electron/src/assets/i18n/ru.json @@ -168,7 +168,7 @@ "BETA_ADDON_CHANNEL": "Бета", "CHANNEL_SUBMENU_TITLE": "Тип выпуска", "IGNORE_ADDON_BUTTON": "Пропускать", - "PROVIDER_SUBMENU_TITLE": "Providers", + "PROVIDER_SUBMENU_TITLE": "Источники", "REINSTALL_ADDON_BUTTON": "Переустановить", "REMOVE_ADDON_BUTTON": "Удалить", "SHOW_FOLDER": "Показать папку", @@ -185,6 +185,7 @@ "TITLE": "Показать колонки" }, "FILTER_LABEL": "Фильтр", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "{count} {count, plural, one{модификация} few{модификации} other{модификаций}}", "JOIN_DISCORD": "Общайтесь с нами в Discord", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "Новые установленные модификации будут автоматически обновляться по умолчанию", "AUTO_UPDATE_LABEL": "Автообновление", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "Папка которая содержит папку клиента {clientTypeName} – \"{clientFolderName}\"", "CLIENT_TYPE_PATH_LABEL": "Путь для {clientTypeName}", "DEFAULT_ADDON_CHANNEL_LABEL": "Тип выпуска модификации по умолчанию", diff --git a/wowup-electron/src/assets/i18n/zh-TW.json b/wowup-electron/src/assets/i18n/zh-TW.json index 7383e2ce..5eed1782 100644 --- a/wowup-electron/src/assets/i18n/zh-TW.json +++ b/wowup-electron/src/assets/i18n/zh-TW.json @@ -185,6 +185,7 @@ "TITLE": "顯示列表項" }, "FILTER_LABEL": "篩選", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "共 {count} 個插件", "JOIN_DISCORD": "在 Discord 上與我們交流(英語)", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "新安裝的插件將預設設定為自動更新", "AUTO_UPDATE_LABEL": "自動更新", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "請選擇 {clientTypeName} 客戶端路徑(\"{clientFolderName}\" 的上級路徑)", "CLIENT_TYPE_PATH_LABEL": "{clientTypeName} 路徑", "DEFAULT_ADDON_CHANNEL_LABEL": "預設插件更新通道", diff --git a/wowup-electron/src/assets/i18n/zh.json b/wowup-electron/src/assets/i18n/zh.json index fe3a992a..ca4377b7 100644 --- a/wowup-electron/src/assets/i18n/zh.json +++ b/wowup-electron/src/assets/i18n/zh.json @@ -185,6 +185,7 @@ "TITLE": "显示列表项" }, "FILTER_LABEL": "筛选", + "MULTIPLE_PROVIDERS_TOOLTIP": "This addon has multiple providers", "PAGE_CONTEXT_FOOTER": { "ADDONS_INSTALLED": "共 {count} 个插件", "JOIN_DISCORD": "在 Discord 上与我们交流(英语)", @@ -276,6 +277,10 @@ "WOW": { "AUTO_UPDATE_DESCRIPTION": "新安装的插件将默认设置为自动更新", "AUTO_UPDATE_LABEL": "自动更新", + "CLEAR_INSTALL_LOCATION_DIALOG": { + "MESSAGE": "Are you sure you want to clear the install path for {clientName}? This will remove all stored addon information for this client.\n\nYour addon folders will not be removed.", + "TITLE": "Clear Install Location?" + }, "CLIENT_TYPE_INPUT_HINT": "请选择 {clientTypeName} 客户端路径(\"{clientFolderName}\" 的上级路径)", "CLIENT_TYPE_PATH_LABEL": "{clientTypeName} 路径", "DEFAULT_ADDON_CHANNEL_LABEL": "默认插件更新通道", diff --git a/wowup-electron/src/common/constants.ts b/wowup-electron/src/common/constants.ts index 9c1818c5..a649fbbf 100644 --- a/wowup-electron/src/common/constants.ts +++ b/wowup-electron/src/common/constants.ts @@ -61,3 +61,6 @@ export const ALLIANCE_THEME = "alliance-theme"; export const ALLIANCE_LIGHT_THEME = "alliance-theme-light-theme"; export const DEFAULT_BG_COLOR = "#444444"; export const DEFAULT_LIGHT_BG_COLOR = "#ebedef"; + +// ERRORS +export const ERROR_ADDON_ALREADY_INSTALLED = "ERROR_ADDON_ALREADY_INSTALLED"