mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-13 13:26:43 +02:00
Merge remote-tracking branch 'origin/main' into dev
This commit is contained in:
@ -30,6 +30,7 @@ Currently supported App sources:
|
|||||||
- [Uptodown](https://uptodown.com/)
|
- [Uptodown](https://uptodown.com/)
|
||||||
- [Huawei AppGallery](https://appgallery.huawei.com/)
|
- [Huawei AppGallery](https://appgallery.huawei.com/)
|
||||||
- [Tencent App Store](https://sj.qq.com/)
|
- [Tencent App Store](https://sj.qq.com/)
|
||||||
|
- [CoolApk](https://coolapk.com/)
|
||||||
- [RuStore](https://rustore.ru/)
|
- [RuStore](https://rustore.ru/)
|
||||||
- Jenkins Jobs
|
- Jenkins Jobs
|
||||||
- [APKMirror](https://apkmirror.com/) (Track-Only)
|
- [APKMirror](https://apkmirror.com/) (Track-Only)
|
||||||
|
@ -320,6 +320,7 @@
|
|||||||
"stayOneVersionBehind": "Stay one version behind latest",
|
"stayOneVersionBehind": "Stay one version behind latest",
|
||||||
"refreshBeforeDownload": "Refresh app details before download",
|
"refreshBeforeDownload": "Refresh app details before download",
|
||||||
"tencentAppStore": "Tencent App Store",
|
"tencentAppStore": "Tencent App Store",
|
||||||
|
"coolApk": "CoolApk",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"smartname": "Name (smart)",
|
"smartname": "Name (smart)",
|
||||||
"sortMethod": "Sort method",
|
"sortMethod": "Sort method",
|
||||||
|
379
assets/translations/pt-BR.json
Normal file
379
assets/translations/pt-BR.json
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
{
|
||||||
|
"noVersionFound": "Não foi possível determinar a versão do lançamento",
|
||||||
|
"urlMatchesNoSource": "A URL não corresponde com nenhuma fonte conhecida",
|
||||||
|
"cantInstallOlderVersion": "Não é possível instalar uma versão mais antiga de um app",
|
||||||
|
"functionNotImplemented": "Essa classe não implementou esse recurso ainda",
|
||||||
|
"placeholder": "Espaço reservado",
|
||||||
|
"someErrors": "Ocorreram alguns erros",
|
||||||
|
"unexpectedError": "Erro inesperado",
|
||||||
|
"ok": "Ok",
|
||||||
|
"and": "e",
|
||||||
|
"githubPATLabel": "Token de acesso pessoal do GitHub (aumenta o limite de taxa)",
|
||||||
|
"includePrereleases": "Incluir pré-lançamentos",
|
||||||
|
"filterReleaseTitlesByRegEx": "Filtrar títulos de lançamentos por expressão regular",
|
||||||
|
"invalidRegEx": "Expressão regular inválida",
|
||||||
|
"noDescription": "Sem descrição",
|
||||||
|
"cancel": "Cancelar",
|
||||||
|
"continue": "Continuar",
|
||||||
|
"requiredInBrackets": "(obrigatório)",
|
||||||
|
"colour": "Cor",
|
||||||
|
"standard": "Padrão",
|
||||||
|
"custom": "Personalizado",
|
||||||
|
"useMaterialYou": "Usar Material You",
|
||||||
|
"githubStarredRepos": "Repositórios com estrela do GitHub",
|
||||||
|
"uname": "Nome de usuário",
|
||||||
|
"xIsTrackOnly": "{} é somente de rastreio",
|
||||||
|
"source": "Fonte",
|
||||||
|
"app": "App",
|
||||||
|
"appsFromSourceAreTrackOnly": "Apps desta fonte são somente para rastreamento.",
|
||||||
|
"youPickedTrackOnly": "Você selecionou a opção de somente rastreamento.",
|
||||||
|
"cancelled": "Cancelado",
|
||||||
|
"appAlreadyAdded": "O app já foi adicionado",
|
||||||
|
"alreadyUpToDateQuestion": "O app já está atualizado?",
|
||||||
|
"addApp": "Adicionar app",
|
||||||
|
"appSourceURL": "URL da fonte do app",
|
||||||
|
"error": "Erro",
|
||||||
|
"add": "Adicionar",
|
||||||
|
"searchSomeSourcesLabel": "Pesquisar (somente algumas fontes)",
|
||||||
|
"search": "Pesquisar",
|
||||||
|
"additionalOptsFor": "Opções adicionais de {}",
|
||||||
|
"supportedSources": "Fontes suportadas",
|
||||||
|
"trackOnlyInBrackets": "(somente rastreamento)",
|
||||||
|
"searchableInBrackets": "(pesquisável)",
|
||||||
|
"appsString": "Apps",
|
||||||
|
"noAppsForFilter": "Nenhum app pro filtro",
|
||||||
|
"byX": "Por {}",
|
||||||
|
"percentProgress": "Progresso: {}%",
|
||||||
|
"pleaseWait": "Por favor aguarde",
|
||||||
|
"notInstalled": "Não instalado",
|
||||||
|
"pseudoVersion": "pseudo-versão",
|
||||||
|
"selectAll": "Selecionar tudo",
|
||||||
|
"deselectX": "Desselecionar {}",
|
||||||
|
"removeSelectedAppsQuestion": "Remover os apps selecionados?",
|
||||||
|
"removeSelectedApps": "Remover apps selecionados",
|
||||||
|
"updateX": "Atualizar {}",
|
||||||
|
"installX": "Instalar {}",
|
||||||
|
"markXTrackOnlyAsUpdated": "Marcar {}\n(somente rastreamento)\ncomo atualizado",
|
||||||
|
"changeX": "Alterar {}",
|
||||||
|
"installUpdateApps": "Instalar/atualizar apps",
|
||||||
|
"installUpdateSelectedApps": "Instalar/atualizar apps selecionados",
|
||||||
|
"no": "Não",
|
||||||
|
"yes": "Sim",
|
||||||
|
"markSelectedAppsUpdated": "Marcar apps selecionados como atualizados",
|
||||||
|
"pinToTop": "Fixar ao topo",
|
||||||
|
"unpinFromTop": "Desfixar do topo",
|
||||||
|
"resetInstallStatusForSelectedAppsQuestion": "Redefinir o estado de instalação dos apps selecionados?",
|
||||||
|
"customLinkMessage": "Esses links funcionarão em dispositivos com o Obtainium instalado",
|
||||||
|
"shareAppConfigLinks": "Compartilhar configuração do app como um link HTML",
|
||||||
|
"shareSelectedAppURLs": "Compartilhar as URLs dos apps selecionados",
|
||||||
|
"resetInstallStatus": "Redefinir estado de instalação",
|
||||||
|
"more": "Mais",
|
||||||
|
"removeOutdatedFilter": "Remover filtro de apps desatualizados",
|
||||||
|
"showOutdatedOnly": "Mostrar somente apps desatualizados",
|
||||||
|
"filter": "Filtro",
|
||||||
|
"filterApps": "Filtrar apps",
|
||||||
|
"appName": "Nome do app",
|
||||||
|
"author": "Autor",
|
||||||
|
"upToDateApps": "Apps atualizados",
|
||||||
|
"nonInstalledApps": "Apps não instalados",
|
||||||
|
"importExport": "Importar/Exportar",
|
||||||
|
"exportedTo": "Exportado para {}",
|
||||||
|
"obtainiumExport": "Exportação do Obtainium",
|
||||||
|
"invalidInput": "Entrada inválida",
|
||||||
|
"importedX": "{} importado(s)",
|
||||||
|
"obtainiumImport": "Importação do Obtainium",
|
||||||
|
"searchQuery": "Consulta de pesquisa",
|
||||||
|
"appURLList": "Lista de URLs dos apps",
|
||||||
|
"searchX": "Pesquisar {}",
|
||||||
|
"noResults": "Nenhum resultado encontrado",
|
||||||
|
"importX": "Importar {}",
|
||||||
|
"importErrors": "Erros de importação",
|
||||||
|
"importedXOfYApps": "{} de {} foram importados.",
|
||||||
|
"followingURLsHadErrors": "As seguintes URLs tiveram erros:",
|
||||||
|
"selectURL": "Selecionar URL",
|
||||||
|
"selectURLs": "Selecionar URLs",
|
||||||
|
"pick": "Escolher",
|
||||||
|
"theme": "Tema",
|
||||||
|
"dark": "Escuro",
|
||||||
|
"light": "Claro",
|
||||||
|
"followSystem": "Seguir o sistema",
|
||||||
|
"useBlackTheme": "Usar o tema escuro de preto profundo",
|
||||||
|
"appSortBy": "Ordenar apps por",
|
||||||
|
"authorName": "Autor/nome",
|
||||||
|
"nameAuthor": "Nome/autor",
|
||||||
|
"asAdded": "Como adicionados",
|
||||||
|
"appSortOrder": "Ordem dos apps",
|
||||||
|
"ascending": "Crescente",
|
||||||
|
"descending": "Decrescente",
|
||||||
|
"bgUpdateCheckInterval": "Intervalo de busca por atualizações em segundo plano",
|
||||||
|
"neverManualOnly": "Nunca - somente manualmente",
|
||||||
|
"appearance": "Aparência",
|
||||||
|
"pinUpdates": "Fixar atualizações no topo da tela de apps",
|
||||||
|
"updates": "Atualizações",
|
||||||
|
"sourceSpecific": "Específico à fonte",
|
||||||
|
"appSource": "Fonte do app",
|
||||||
|
"noLogs": "Nenhum registro",
|
||||||
|
"appLogs": "Registros do app",
|
||||||
|
"close": "Fechar",
|
||||||
|
"share": "Compartilhar",
|
||||||
|
"pickAnAPK": "Selecione um APK",
|
||||||
|
"appHasMoreThanOnePackage": "{} tem mais de um pacote:",
|
||||||
|
"deviceSupportsXArch": "Seu dispositivo suporta a arquitetura de CPU {}.",
|
||||||
|
"warning": "Alerta",
|
||||||
|
"sourceIsXButPackageFromYPrompt": "A fonte do app é '{}' mas o pacote de lançamento vem de '{}'. Continuar mesmo assim?",
|
||||||
|
"updatesAvailable": "Atualizações disponíveis",
|
||||||
|
"noNewUpdates": "Nenhuma atualização disponível.",
|
||||||
|
"xHasAnUpdate": "{} tem uma atualização.",
|
||||||
|
"appsUpdated": "Apps atualizados",
|
||||||
|
"appsNotUpdated": "Falhou ao atualizar os aplicativos",
|
||||||
|
"appsUpdatedNotifDescription": "Notifica o usuário que atualizações de um ou mais apps foram aplicadas em segundo plano",
|
||||||
|
"xWasNotUpdatedToY": "Falha ao atualizar {} para a versão {}.",
|
||||||
|
"errorCheckingUpdates": "Ocorreu um erro ao buscar atualizações",
|
||||||
|
"appsRemoved": "Apps removidos",
|
||||||
|
"appsRemovedNotifDescription": "Notifica o usuário que um ou mais apps foram removidos devido a erros ao carregá-los",
|
||||||
|
"xWasRemovedDueToErrorY": "{} for removido devido ao erro: {}",
|
||||||
|
"completeAppInstallation": "Concluir instalação do app",
|
||||||
|
"completeAppInstallationNotifDescription": "Pede pro usuário voltar ao Obtainium para concluir a instalação de um app",
|
||||||
|
"checkingForUpdates": "Buscando atualizações",
|
||||||
|
"checkingForUpdatesNotifDescription": "Notificação transitória que aparece ao buscar atualizações",
|
||||||
|
"pleaseAllowInstallPerm": "Permita que o Obtainium instale apps",
|
||||||
|
"trackOnly": "Somente rastreamento",
|
||||||
|
"errorWithHttpStatusCode": "Erro {}",
|
||||||
|
"unknown": "Desconhecido",
|
||||||
|
"none": "Nenhum",
|
||||||
|
"never": "Nunca",
|
||||||
|
"latestVersionX": "Mais recente: {}",
|
||||||
|
"installedVersionX": "Instalado: {}",
|
||||||
|
"lastUpdateCheckX": "Última busca por atualizações: {}",
|
||||||
|
"remove": "Remover",
|
||||||
|
"yesMarkUpdated": "Sim, marcar como atualizado",
|
||||||
|
"fdroid": "Oficial do F-Droid",
|
||||||
|
"appIdOrName": "ID do app ou nome",
|
||||||
|
"appId": "ID do app",
|
||||||
|
"reposHaveMultipleApps": "Repositórios podem conter vários apps",
|
||||||
|
"fdroidThirdPartyRepo": "Repositório de terceiros do F-Droid",
|
||||||
|
"install": "Instalar",
|
||||||
|
"markInstalled": "Marcar como instalado",
|
||||||
|
"update": "Atualizar",
|
||||||
|
"markUpdated": "Marcar como atualizado",
|
||||||
|
"additionalOptions": "Opções adicionais",
|
||||||
|
"downloadingX": "Baixando {}",
|
||||||
|
"downloadX": "Baixar {}",
|
||||||
|
"downloadedX": "{} foi baixado",
|
||||||
|
"releaseAsset": "Item de lançamento",
|
||||||
|
"downloadNotifDescription": "Notifica o usuário do progresso ao baixar um app",
|
||||||
|
"noAPKFound": "Nenhum APK encontrado",
|
||||||
|
"noVersionDetection": "Sem detecção de versão",
|
||||||
|
"categorize": "Categorizar",
|
||||||
|
"categories": "Categorias",
|
||||||
|
"category": "Categoria",
|
||||||
|
"noCategory": "Nenhuma categoria",
|
||||||
|
"deleteCategoriesQuestion": "Excluir categorias?",
|
||||||
|
"addCategory": "Adicionar categoria",
|
||||||
|
"label": "Rótulo",
|
||||||
|
"language": "Idioma",
|
||||||
|
"copiedToClipboard": "Copiado para a área de transferência",
|
||||||
|
"storagePermissionDenied": "Permissão de armazenamento negada",
|
||||||
|
"selectedCategorizeWarning": "Isso substituirá a configuração de categoria existente dos apps selecionados.",
|
||||||
|
"filterAPKsByRegEx": "Filtrar APKs por expressão regular",
|
||||||
|
"removeFromObtainium": "Remover do Obtainium",
|
||||||
|
"onlyWorksWithNonVersionDetectApps": "Funciona somente em apps com a detecção de versão desativada.",
|
||||||
|
"releaseTitleAsVersion": "Usar título do lançamento como número da versão",
|
||||||
|
"changes": "Alterações",
|
||||||
|
"releaseDate": "Data de lançamento",
|
||||||
|
"importFromURLsInFile": "Importar das URLs em arquivo (como OPML)",
|
||||||
|
"versionDetectionExplanation": "Combinar o número da versão com a versão detectada pelo sistema",
|
||||||
|
"versionDetection": "Detecção de versão",
|
||||||
|
"standardVersionDetection": "Detecção de versão padrão",
|
||||||
|
"groupByCategory": "Agrupar por categoria",
|
||||||
|
"autoApkFilterByArch": "Tentar filtrar APKs pela arquitetura da CPU quando possível",
|
||||||
|
"autoLinkFilterByArch": "Tentar filtrar links pela arquitetura da CPU quando possível",
|
||||||
|
"overrideSource": "Sobrescrever fonte",
|
||||||
|
"dontShowAgain": "Não mostrar isso novamente",
|
||||||
|
"dontShowTrackOnlyWarnings": "Não mostrar alertas de \"somente rastreamento\"",
|
||||||
|
"moveNonInstalledAppsToBottom": "Mover apps não instalados ao final da tela de apps",
|
||||||
|
"gitlabPATLabel": "Token de acesso pessoal do GitLab",
|
||||||
|
"about": "Sobre",
|
||||||
|
"requiresCredentialsInSettings": "{} precisa de credenciais adicionais (nas Configurações)",
|
||||||
|
"checkOnStart": "Buscar atualizações ao abrir o app",
|
||||||
|
"removeOnExternalUninstall": "Remover automaticamente apps desinstalados externamente",
|
||||||
|
"pickHighestVersionCode": "Selecionar APK de versão mais alta automaticamente",
|
||||||
|
"disablePageTransitions": "Desativar animações de transição de tela",
|
||||||
|
"reversePageTransitions": "Inverter animações de transição de tela",
|
||||||
|
"minStarCount": "Número de estrelas mínimo",
|
||||||
|
"addInfoBelow": "Adicione essa informação abaixo.",
|
||||||
|
"addInfoInSettings": "Adicione essa informação nas Configurações.",
|
||||||
|
"sortByLastLinkSegment": "Ordenar somente pelo ultimo segmento do link",
|
||||||
|
"filterReleaseNotesByRegEx": "Filtrar notas de lançamento por expressão regular",
|
||||||
|
"appsPossiblyUpdated": "Tentativas de atualização de apps",
|
||||||
|
"xWasPossiblyUpdatedToY": "{} pode ter sido atualizado para a versão {}.",
|
||||||
|
"enableBackgroundUpdates": "Ativar atualizações em segundo plano",
|
||||||
|
"backgroundUpdateReqsExplanation": "Atualizações em segundo plano podem não funcionar com todos os apps.",
|
||||||
|
"backgroundUpdateLimitsExplanation": "O sucesso de uma instalação em segundo plano só pode ser determinada ao abrir o Obtainium.",
|
||||||
|
"verifyLatestTag": "Verificar a tag 'mais recente'",
|
||||||
|
"filterByLinkText": "Filtrar links por texto do link",
|
||||||
|
"intermediateLinkNotFound": "Link intermediário não encontrado",
|
||||||
|
"intermediateLink": "Link intermediário",
|
||||||
|
"exemptFromBackgroundUpdates": "Isento de atualizações em segundo plano (caso ativadas)",
|
||||||
|
"bgUpdatesWhileChargingOnly": "Desativar atualizações em segundo plano fora do carregador",
|
||||||
|
"autoSelectHighestVersionCode": "Selecionar automaticamente APK com o código de versão mais alto",
|
||||||
|
"versionExtractionRegEx": "ExReg de extração do número da versão",
|
||||||
|
"trimVersionString": "Cortar número da versal com ExReg",
|
||||||
|
"matchGroupToUseForX": "Corresponder grupo para o uso em \"{}\"",
|
||||||
|
"highlightTouchTargets": "Acentuar alvos de toque menos óbvios",
|
||||||
|
"pickExportDir": "Selecionar pasta de exportação",
|
||||||
|
"autoExportOnChanges": "Exportar automaticamente ao ocorrer alterações",
|
||||||
|
"includeSettings": "Incluir configurações",
|
||||||
|
"trySelectingSuggestedVersionCode": "Tente selecionar o APK com o código de versão sugerido",
|
||||||
|
"dontSortReleasesList": "Manter ordem de lançamento da API",
|
||||||
|
"reverseSort": "Ordem inversa",
|
||||||
|
"takeFirstLink": "Usar o primeiro link",
|
||||||
|
"skipSort": "Pular ordenação",
|
||||||
|
"debugMenu": "Menu de depuração",
|
||||||
|
"runBgCheckNow": "Executar busca por atualizações em segundo plano agora",
|
||||||
|
"versionExtractWholePage": "Aplicar ExReg de extração de número de versão à página inteira",
|
||||||
|
"installing": "Instalando",
|
||||||
|
"updatesAvailableNotifChannel": "Atualizações disponíveis",
|
||||||
|
"appsUpdatedNotifChannel": "Apps atualizados",
|
||||||
|
"appsPossiblyUpdatedNotifChannel": "Tentativas de atualização de apps",
|
||||||
|
"errorCheckingUpdatesNotifChannel": "Erro ao buscar atualizações",
|
||||||
|
"appsRemovedNotifChannel": "Apps removidos",
|
||||||
|
"downloadingXNotifChannel": "Baixando {}",
|
||||||
|
"checkingForUpdatesNotifChannel": "Buscando atualizações",
|
||||||
|
"onlyCheckInstalledOrTrackOnlyApps": "Buscar atualizações somente para apps instalados e de somente rastreamento",
|
||||||
|
"supportFixedAPKURL": "Suportar URLs de APK fixas",
|
||||||
|
"parallelDownloads": "Permitir downloads em paralelo",
|
||||||
|
"shizukuBinderNotFound": "Serviço Shizuku não está em execução",
|
||||||
|
"shizukuOld": "Versão do Shizuku antiga (<11) - atualize",
|
||||||
|
"shizukuPretendToBeGooglePlay": "Definir Google Play como a fonte de instalação (se o Shizuku é usado)",
|
||||||
|
"useSystemFont": "Usar a fonte do sistema",
|
||||||
|
"useVersionCodeAsOSVersion": "Usar código de versão do app como a versão detectada pelo sistema",
|
||||||
|
"requestHeader": "Cabeçalho da solicitação",
|
||||||
|
"defaultPseudoVersioningMethod": "Método de pseudo-versão padrão",
|
||||||
|
"partialAPKHash": "Hash do APK parcial",
|
||||||
|
"APKLinkHash": "Hash do link do APK",
|
||||||
|
"directAPKLink": "Link direto ao APK",
|
||||||
|
"pseudoVersionInUse": "Uma pseudo-versão está em uso",
|
||||||
|
"installed": "Instalado",
|
||||||
|
"latest": "Mais recente",
|
||||||
|
"invertRegEx": "Inverter expressão regular",
|
||||||
|
"note": "Observação",
|
||||||
|
"badDownload": "O APK não pode ser interpretado (incompatível ou baixado parcialmente)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Compartilhar apps novos com o AppVerifier (se disponível)",
|
||||||
|
"appVerifierInstructionToast": "Compartilhe com o AppVerifier, e volte aqui ao estar pronto.",
|
||||||
|
"wiki": "Ajuda/Wiki",
|
||||||
|
"crowdsourcedConfigsShort": "Configurações de app da comunidade",
|
||||||
|
"allowInsecure": "Permitir solicitações de HTTP inseguras",
|
||||||
|
"stayOneVersionBehind": "Ficar uma versão antes da mais recente",
|
||||||
|
"refreshBeforeDownload": "Atualizar detalhes do app antes de baixar",
|
||||||
|
"tencentAppStore": "Loja de Apps da Tencent",
|
||||||
|
"name": "Nome",
|
||||||
|
"smartname": "Nome (inteligente)",
|
||||||
|
"welcome": "Boas vindas",
|
||||||
|
"removeAppQuestion": {
|
||||||
|
"one": "Remover app?",
|
||||||
|
"other": "Remover apps?"
|
||||||
|
},
|
||||||
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
|
"one": "Muitas solicitações (limitado) - tente novamente em {} minuto",
|
||||||
|
"other": "Muitas solicitações (limitado) - tente novamente em {} minutos"
|
||||||
|
},
|
||||||
|
"bgUpdateGotErrorRetryInMinutes": {
|
||||||
|
"one": "A busca de atualizações em segundo plano encontrou um {}, será agendado uma nova tentativa em {} minuto",
|
||||||
|
"other": "A busca de atualizações em segundo plano encontrou um {}, será agendado uma nova tentativa em {} minutos"
|
||||||
|
},
|
||||||
|
"apps": {
|
||||||
|
"one": "{} app",
|
||||||
|
"other": "{} apps"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"one": "{} URL",
|
||||||
|
"other": "{} URLs"
|
||||||
|
},
|
||||||
|
"minute": {
|
||||||
|
"one": "{} minuto",
|
||||||
|
"other": "{} minutos"
|
||||||
|
},
|
||||||
|
"hour": {
|
||||||
|
"one": "{} hora",
|
||||||
|
"other": "{} horas"
|
||||||
|
},
|
||||||
|
"day": {
|
||||||
|
"one": "{} dia",
|
||||||
|
"other": "{} dias"
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesAvailable": {
|
||||||
|
"one": "{} e mais 1 app têm atualizações.",
|
||||||
|
"other": "{} e mais {} apps têm atualizações."
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesInstalled": {
|
||||||
|
"one": "{} e mais 1 app foram atualizados.",
|
||||||
|
"other": "{} e mais {} apps foram atualizados."
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesFailed": {
|
||||||
|
"one": "Falha ao atualizar {} e mais 1 app.",
|
||||||
|
"other": "Falha ao atualizar {} e mais {} apps."
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||||
|
"one": "{} e mais 1 app podem ter sido atualizados.",
|
||||||
|
"other": "{} e mais {} apps podem ter sido atualizados."
|
||||||
|
},
|
||||||
|
"apk": {
|
||||||
|
"one": "{} APK",
|
||||||
|
"other": "{} APKs"
|
||||||
|
},
|
||||||
|
"invalidURLForSource": "Não é uma URL de app válida de {}",
|
||||||
|
"noReleaseFound": "Não foi possível encontrar um lançamento adequado",
|
||||||
|
"appIdMismatch": "O ID do pacote baixado não corresponde ao existente",
|
||||||
|
"fallbackToOlderReleases": "Recorrer à lançamentos mais antigos",
|
||||||
|
"dropdownNoOptsError": "ERRO: O MENU DEVE TER PELO MENOS UMA OPÇÃO",
|
||||||
|
"wrongArgNum": "Número errado de argumentos fornecidos",
|
||||||
|
"trackOnlyAppDescription": "As atualizações do app serão rastreadas, mas o Obtainium não baixará ou instalará elas.",
|
||||||
|
"noApps": "Nenhum app",
|
||||||
|
"updateAvailable": "Atualização disponível",
|
||||||
|
"xWillBeRemovedButRemainInstalled": "{} será removido do Obtainium mas continuará instalado no dispositivo.",
|
||||||
|
"markXSelectedAppsAsUpdated": "Marcar os {} apps selecionados como atualizados?",
|
||||||
|
"installStatusOfXWillBeResetExplanation": "Os estados de instalação dos apps selecionados serão redefinidos.\n\nIsso pode ajudar quando a versão exibida no Obtainium está incorreta devido a atualizações malsucedidas ou outros problemas.",
|
||||||
|
"settings": "Configurações",
|
||||||
|
"importFromURLList": "Importar da lista de URLs",
|
||||||
|
"line": "Linha",
|
||||||
|
"importedAppsIdDisclaimer": "Os apps importados podem ser exibidos incorretamente como se não estivessem instalados.\nPara resolver isso, reinstale eles pelo Obtainium.\nIsso não afetará os dados dos apps.\n\nIsso somente afeta a URL e os métodos de importação de terceiros.",
|
||||||
|
"followSystemThemeExplanation": "Só é possível seguir o tema do sistema ao usar aplicativos de terceiros",
|
||||||
|
"appNotFound": "O app não foi encontrado",
|
||||||
|
"updatesAvailableNotifDescription": "Notifica o usuário que atualizações estão disponíveis para um ou mais apps rastreados pelo Obtainium",
|
||||||
|
"xWasUpdatedToY": "{} foi atualizado para a versão {}.",
|
||||||
|
"showWebInAppView": "Mostrar a fonte da pagina web na tela de apps",
|
||||||
|
"deviceSupportsFollowingArchs": "Seu dispositivo suporta as seguintes arquiteturas de CPU:",
|
||||||
|
"errorCheckingUpdatesNotifDescription": "Uma notificação que mostra quando a busca de atualizações em segundo plano falha",
|
||||||
|
"obtainiumMustBeOpenToInstallApps": "O Obtainium precisa estar aberto para instalar apps",
|
||||||
|
"versionCorrectionDisabled": "Correção de versão desativada (o plugin parece não funcionar)",
|
||||||
|
"appWithIdOrNameNotFound": "Nenhum app foi encontrado com aquele ID ou nome",
|
||||||
|
"disableVersionDetection": "Desativar detecção de versão",
|
||||||
|
"noVersionDetectionExplanation": "Essa opção só seve ser usada para apps aonde a detecção de versão não funciona corretamente.",
|
||||||
|
"noCategories": "Nenhuma categoria",
|
||||||
|
"categoryDeleteWarning": "Todos os apps em categorias excluídas ficarão sem categoria.",
|
||||||
|
"uninstallFromDevice": "Desinstalar do dispositivo",
|
||||||
|
"releaseDateAsVersion": "Usar data de lançamento como número da versão",
|
||||||
|
"dontShowAPKOriginWarnings": "Não mostrar alertas de origem dos APKs",
|
||||||
|
"tryInferAppIdFromCode": "Tentar inferir o ID do app pelo código fonte",
|
||||||
|
"checkUpdateOnDetailPage": "Buscar atualizações ao abrir a tela de detalhes de um app",
|
||||||
|
"githubSourceNote": "O limite de taxa do GitHub pode ser evitado ao usar uma chave de API.",
|
||||||
|
"customLinkFilterRegex": "Filtro de link de APK personalizado por expressão regular (padrão '.apk$')",
|
||||||
|
"appsPossiblyUpdatedNotifDescription": "Notifica o usuário que atualizações de um ou mais apps podem ter sido aplicadas em segundo plano",
|
||||||
|
"bgUpdatesOnWiFiOnly": "Desativar atualizações em segundo plano fora do Wi-Fi",
|
||||||
|
"matchGroupToUse": "Corresponder grupo para o uso para a extração do número da versão por ExReg",
|
||||||
|
"filterVersionsByRegEx": "Filtrar versões por expressão regular",
|
||||||
|
"completeAppInstallationNotifChannel": "Concluir instalação do app",
|
||||||
|
"useShizuku": "Usar Shizuku ou Sui para instalação",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Usar o envio de item mais recente como a data de lançamento",
|
||||||
|
"crowdsourcedConfigsLabel": "Configurações de app pela comunidade (use ao seu próprio risco)",
|
||||||
|
"releaseDateAsVersionExplanation": "Essa opção só deve ser usada para apps quais a detecção de versão não funciona corretamente, mas uma data de lançamento está disponível.",
|
||||||
|
"intermediateLinkRegex": "Filtrar por um link 'intermediário' para visitar",
|
||||||
|
"bgTaskStarted": "Tarefa em segundo plano iniada - verifique os registros.",
|
||||||
|
"skipUpdateNotifications": "Pular notificações de atualização",
|
||||||
|
"selectX": "Selecionar {}",
|
||||||
|
"shizukuOldAndroidWithADB": "Shizuku sendo executado no Android < 8.1 com ADB - atualize o Android ou use o Sui",
|
||||||
|
"selfHostedNote": "O menu de opções \"{}\" pode ser usado para alcançar instâncias hospedadas-por-você/personalizadas de qualquer fonte.",
|
||||||
|
"sortMethod": "Método de ordenação",
|
||||||
|
"documentationLinksNote": "A página do Obtainium no GitHub visível abaixo contém links de vídeos, artigos, discussões, e outros recursos que podem te ajudar ao usar o app."
|
||||||
|
}
|
@ -320,6 +320,7 @@
|
|||||||
"stayOneVersionBehind": "比最新版本晚一个版本",
|
"stayOneVersionBehind": "比最新版本晚一个版本",
|
||||||
"refreshBeforeDownload": "下载前刷新应用程序详细信息",
|
"refreshBeforeDownload": "下载前刷新应用程序详细信息",
|
||||||
"tencentAppStore": "腾讯应用宝",
|
"tencentAppStore": "腾讯应用宝",
|
||||||
|
"coolApk": "酷安",
|
||||||
"name": "名称",
|
"name": "名称",
|
||||||
"smartname": "姓名(智能)",
|
"smartname": "姓名(智能)",
|
||||||
"sortMethod": "排序方法",
|
"sortMethod": "排序方法",
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
<li>APKMirror (Track-Only)</li>
|
<li>APKMirror (Track-Only)</li>
|
||||||
<li>Huawei AppGallery</li>
|
<li>Huawei AppGallery</li>
|
||||||
<li>Tencent App Store</li>
|
<li>Tencent App Store</li>
|
||||||
|
<li>CoolApk</li>
|
||||||
<li>Jenkins Jobs</li>
|
<li>Jenkins Jobs</li>
|
||||||
<li>RuStore</li>
|
<li>RuStore</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
<li>APKMirror (Track-Only)</li>
|
<li>APKMirror (Track-Only)</li>
|
||||||
<li>Huawei AppGallery</li>
|
<li>Huawei AppGallery</li>
|
||||||
<li>Tencent App Store</li>
|
<li>Tencent App Store</li>
|
||||||
|
<li>CoolApk</li>
|
||||||
<li>Jenkins Jobs</li>
|
<li>Jenkins Jobs</li>
|
||||||
<li>RuStore</li>
|
<li>RuStore</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
173
lib/app_sources/coolapk.dart
Normal file
173
lib/app_sources/coolapk.dart
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'package:bcrypt/bcrypt.dart';
|
||||||
|
import 'package:crypto/crypto.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:obtainium/custom_errors.dart';
|
||||||
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
// kanged from https://github.com/DUpdateSystem/UpgradeAll/blob/b2f92c9/core-websdk/src/main/java/net/xzos/upgradeall/core/websdk/api/client_proxy/hubs/CoolApk.kt
|
||||||
|
class CoolApk extends AppSource {
|
||||||
|
CoolApk() {
|
||||||
|
name = tr('coolApk');
|
||||||
|
hosts = ['www.coolapk.com', 'api2.coolapk.com'];
|
||||||
|
allowSubDomains = true;
|
||||||
|
naiveStandardVersionDetection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String sourceSpecificStandardizeURL(String url, {bool forSelection = false}) {
|
||||||
|
RegExp standardUrlRegEx = RegExp(
|
||||||
|
r'^https?://(www\.)?coolapk\.com/apk/[^/]+',
|
||||||
|
caseSensitive: false);
|
||||||
|
var match = standardUrlRegEx.firstMatch(url);
|
||||||
|
if (match == null) {
|
||||||
|
throw InvalidURLError(name);
|
||||||
|
}
|
||||||
|
String standardizedUrl = match.group(0)!;
|
||||||
|
return standardizedUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?> tryInferringAppId(String standardUrl,
|
||||||
|
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||||
|
String appId = Uri.parse(standardUrl).pathSegments.last;
|
||||||
|
return appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
|
String standardUrl,
|
||||||
|
Map<String, dynamic> additionalSettings,
|
||||||
|
) async {
|
||||||
|
String appId = (await tryInferringAppId(standardUrl))!;
|
||||||
|
String apiUrl = 'https://api2.coolapk.com';
|
||||||
|
|
||||||
|
// get latest
|
||||||
|
var detailUrl = '$apiUrl/v6/apk/detail?id=$appId';
|
||||||
|
var headers = await getRequestHeaders(additionalSettings);
|
||||||
|
var res = await sourceRequest(detailUrl, additionalSettings);
|
||||||
|
|
||||||
|
if (res.statusCode != 200) {
|
||||||
|
throw getObtainiumHttpError(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
var json = jsonDecode(res.body);
|
||||||
|
if (json['status'] == -2 || json['data'] == null) {
|
||||||
|
throw NoReleasesError();
|
||||||
|
}
|
||||||
|
|
||||||
|
var detail = json['data'];
|
||||||
|
String version = detail['apkversionname'].toString();
|
||||||
|
String appName = detail['title'].toString();
|
||||||
|
String author = detail['developername']?.toString() ?? 'CoolApk';
|
||||||
|
String changelog = detail['changelog']?.toString() ?? '';
|
||||||
|
int? releaseDate = detail['lastupdate'] != null
|
||||||
|
? (detail['lastupdate'] is int
|
||||||
|
? detail['lastupdate'] * 1000
|
||||||
|
: int.parse(detail['lastupdate'].toString()) * 1000)
|
||||||
|
: null;
|
||||||
|
String aid = detail['id'].toString();
|
||||||
|
|
||||||
|
// get apk url
|
||||||
|
String apkUrl = await _getLatestApkUrl(apiUrl, appId, aid, version, headers);
|
||||||
|
if (apkUrl.isEmpty) {
|
||||||
|
throw NoAPKError();
|
||||||
|
}
|
||||||
|
|
||||||
|
String apkName = '${appId}_$version.apk';
|
||||||
|
|
||||||
|
return APKDetails(
|
||||||
|
version,
|
||||||
|
[MapEntry(apkName, apkUrl)],
|
||||||
|
AppNames(author, appName),
|
||||||
|
releaseDate: releaseDate != null
|
||||||
|
? DateTime.fromMillisecondsSinceEpoch(releaseDate)
|
||||||
|
: null,
|
||||||
|
changeLog: changelog,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> _getLatestApkUrl(String apiUrl, String appId, String aid,
|
||||||
|
String version, Map<String, String>? headers) async {
|
||||||
|
String url = '$apiUrl/v6/apk/download?pn=$appId&aid=$aid';
|
||||||
|
var res = await sourceRequest(url, {}, followRedirects: false);
|
||||||
|
if (res.statusCode >= 300 && res.statusCode < 400) {
|
||||||
|
String location = res.headers['location'] ?? '';
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Map<String, String>?> getRequestHeaders(
|
||||||
|
Map<String, dynamic> additionalSettings,
|
||||||
|
{bool forAPKDownload = false}) async {
|
||||||
|
var tokenPair = _getToken();
|
||||||
|
// CoolAPK header
|
||||||
|
return {
|
||||||
|
'User-Agent':
|
||||||
|
'Dalvik/2.1.0 (Linux; U; Android 9; MI 8 SE MIUI/9.5.9) (#Build; Xiaomi; MI 8 SE; PKQ1.181121.001; 9) +CoolMarket/12.4.2-2208241-universal',
|
||||||
|
'X-App-Id': 'com.coolapk.market',
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
'X-Sdk-Int': '30',
|
||||||
|
'X-App-Mode': 'universal',
|
||||||
|
'X-App-Channel': 'coolapk',
|
||||||
|
'X-Sdk-Locale': 'zh-CN',
|
||||||
|
'X-App-Version': '12.4.2',
|
||||||
|
'X-Api-Supported': '2208241',
|
||||||
|
'X-App-Code': '2208241',
|
||||||
|
'X-Api-Version': '12',
|
||||||
|
'X-App-Device': tokenPair['deviceCode']!,
|
||||||
|
'X-Dark-Mode': '0',
|
||||||
|
'X-App-Token': tokenPair['token']!,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> _getToken() {
|
||||||
|
final rand = Random();
|
||||||
|
|
||||||
|
String randHexString(int n) =>
|
||||||
|
List.generate(n, (_) => rand.nextInt(256).toRadixString(16).padLeft(2, '0'))
|
||||||
|
.join()
|
||||||
|
.toUpperCase();
|
||||||
|
|
||||||
|
String randMacAddress() =>
|
||||||
|
List.generate(6, (_) => rand.nextInt(256).toRadixString(16).padLeft(2, '0'))
|
||||||
|
.join(':');
|
||||||
|
|
||||||
|
// 加密算法来自 https://github.com/XiaoMengXinX/FuckCoolapkTokenV2、https://github.com/Coolapk-UWP/Coolapk-UWP
|
||||||
|
// device
|
||||||
|
String aid = randHexString(16);
|
||||||
|
String mac = randMacAddress();
|
||||||
|
const manufactor = 'Google';
|
||||||
|
const brand = 'Google';
|
||||||
|
const model = 'Pixel 5a';
|
||||||
|
const buildNumber = 'SQ1D.220105.007';
|
||||||
|
|
||||||
|
// generate deviceCode
|
||||||
|
String deviceCode =
|
||||||
|
base64.encode('$aid; ; ; $mac; $manufactor; $brand; $model; $buildNumber'.codeUnits);
|
||||||
|
|
||||||
|
// generate timestamp
|
||||||
|
String timeStamp = (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();
|
||||||
|
String base64TimeStamp = base64.encode(timeStamp.codeUnits);
|
||||||
|
String md5TimeStamp = md5.convert(timeStamp.codeUnits).toString();
|
||||||
|
String md5DeviceCode = md5.convert(deviceCode.codeUnits).toString();
|
||||||
|
|
||||||
|
// generate token
|
||||||
|
String token =
|
||||||
|
'token://com.coolapk.market/dcf01e569c1e3db93a3d0fcf191a622c?$md5TimeStamp\$$md5DeviceCode&com.coolapk.market';
|
||||||
|
String base64Token = base64.encode(token.codeUnits);
|
||||||
|
String md5Base64Token = md5.convert(base64Token.codeUnits).toString();
|
||||||
|
String md5Token = md5.convert(token.codeUnits).toString();
|
||||||
|
|
||||||
|
// generate salt and hash
|
||||||
|
String bcryptSalt = '\$2a\$10\$${base64TimeStamp.substring(0, 14)}/${md5Token.substring(0, 6)}u';
|
||||||
|
String bcryptResult = BCrypt.hashpw(md5Base64Token, bcryptSalt);
|
||||||
|
String reBcryptResult = bcryptResult.replaceRange(0, 3, '\$2y');
|
||||||
|
String finalToken = 'v2${base64.encode(reBcryptResult.codeUnits)}';
|
||||||
|
|
||||||
|
return {'deviceCode': deviceCode, 'token': finalToken};
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ import 'package:obtainium/app_sources/apkmirror.dart';
|
|||||||
import 'package:obtainium/app_sources/apkpure.dart';
|
import 'package:obtainium/app_sources/apkpure.dart';
|
||||||
import 'package:obtainium/app_sources/aptoide.dart';
|
import 'package:obtainium/app_sources/aptoide.dart';
|
||||||
import 'package:obtainium/app_sources/codeberg.dart';
|
import 'package:obtainium/app_sources/codeberg.dart';
|
||||||
|
import 'package:obtainium/app_sources/coolapk.dart';
|
||||||
import 'package:obtainium/app_sources/directAPKLink.dart';
|
import 'package:obtainium/app_sources/directAPKLink.dart';
|
||||||
import 'package:obtainium/app_sources/fdroid.dart';
|
import 'package:obtainium/app_sources/fdroid.dart';
|
||||||
import 'package:obtainium/app_sources/fdroidrepo.dart';
|
import 'package:obtainium/app_sources/fdroidrepo.dart';
|
||||||
@ -934,6 +935,7 @@ class SourceProvider {
|
|||||||
Uptodown(),
|
Uptodown(),
|
||||||
HuaweiAppGallery(),
|
HuaweiAppGallery(),
|
||||||
Tencent(),
|
Tencent(),
|
||||||
|
CoolApk(),
|
||||||
Jenkins(),
|
Jenkins(),
|
||||||
APKMirror(),
|
APKMirror(),
|
||||||
RuStore(),
|
RuStore(),
|
||||||
|
@ -124,6 +124,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
|
bcrypt:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: bcrypt
|
||||||
|
sha256: "9dc3f234d5935a76917a6056613e1a6d9b53f7fa56f98e24cd49b8969307764b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.3"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -70,6 +70,7 @@ dependencies:
|
|||||||
url: https://github.com/AlexBacich/shared-storage
|
url: https://github.com/AlexBacich/shared-storage
|
||||||
ref: master
|
ref: master
|
||||||
crypto: ^3.0.3
|
crypto: ^3.0.3
|
||||||
|
bcrypt: ^1.1.3
|
||||||
app_links: ^6.0.1
|
app_links: ^6.0.1
|
||||||
background_fetch: ^1.2.1
|
background_fetch: ^1.2.1
|
||||||
equations: ^5.0.2
|
equations: ^5.0.2
|
||||||
|
Reference in New Issue
Block a user