Compare commits

...

32 Commits

Author SHA1 Message Date
hstyi
dd48dfcd96 chore: add Portuguese (pt-BR) translation 2026-01-16 11:33:30 +08:00
Rodrigo
a227d1a4ff feat: add pt-BR translation (#1367) 2026-01-16 11:28:30 +08:00
dependabot[bot]
7c6d144a89 chore(deps): bump com.qcloud:cos_api from 5.6.259 to 5.6.260.1
Bumps [com.qcloud:cos_api](https://github.com/tencentyun/cos-java-sdk-v5) from 5.6.259 to 5.6.260.1.
- [Release notes](https://github.com/tencentyun/cos-java-sdk-v5/releases)
- [Changelog](https://github.com/tencentyun/cos-java-sdk-v5/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tencentyun/cos-java-sdk-v5/commits)

---
updated-dependencies:
- dependency-name: com.qcloud:cos_api
  dependency-version: 5.6.260.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-12 09:30:31 +08:00
dependabot[bot]
a5434c5cdf chore(deps): bump com.mixpanel:mixpanel-java from 1.5.4 to 1.7.0
Bumps [com.mixpanel:mixpanel-java](https://github.com/mixpanel/mixpanel-java) from 1.5.4 to 1.7.0.
- [Release notes](https://github.com/mixpanel/mixpanel-java/releases)
- [Commits](https://github.com/mixpanel/mixpanel-java/compare/v1.5.4...v1.7.0)

---
updated-dependencies:
- dependency-name: com.mixpanel:mixpanel-java
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-08 08:55:02 +08:00
dependabot[bot]
68bd883305 chore(deps): bump com.fifesoft:rsyntaxtextarea from 3.6.0 to 3.6.1
Bumps [com.fifesoft:rsyntaxtextarea](https://github.com/bobbylight/rsyntaxtextarea) from 3.6.0 to 3.6.1.
- [Release notes](https://github.com/bobbylight/rsyntaxtextarea/releases)
- [Commits](https://github.com/bobbylight/rsyntaxtextarea/compare/3.6.0...3.6.1)

---
updated-dependencies:
- dependency-name: com.fifesoft:rsyntaxtextarea
  dependency-version: 3.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-03 16:45:33 +08:00
dependabot[bot]
3fa2659d59 chore(deps): bump org.mozilla:rhino from 1.8.0 to 1.9.0
Bumps [org.mozilla:rhino](https://github.com/mozilla/rhino) from 1.8.0 to 1.9.0.
- [Release notes](https://github.com/mozilla/rhino/releases)
- [Changelog](https://github.com/mozilla/rhino/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/mozilla/rhino/commits)

---
updated-dependencies:
- dependency-name: org.mozilla:rhino
  dependency-version: 1.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-29 08:31:50 +08:00
hstyi
3ece32e427 chore: handle IPv6 addresses correctly in RDP connection string 2025-12-22 09:13:23 +08:00
hstyi
dad4d26fd8 chore: add "Nothing" option for right-click 2025-12-22 09:12:27 +08:00
dependabot[bot]
9b387c71fc chore(deps): bump org.testcontainers:testcontainers-bom
Bumps [org.testcontainers:testcontainers-bom](https://github.com/testcontainers/testcontainers-java) from 2.0.1 to 2.0.3.
- [Release notes](https://github.com/testcontainers/testcontainers-java/releases)
- [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testcontainers/testcontainers-java/compare/2.0.1...2.0.3)

---
updated-dependencies:
- dependency-name: org.testcontainers:testcontainers-bom
  dependency-version: 2.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-17 19:28:10 +08:00
dependabot[bot]
7ac833b53b chore(deps): bump kotlin from 2.2.21 to 2.3.0
Bumps `kotlin` from 2.2.21 to 2.3.0.

Updates `org.jetbrains.kotlin.jvm` from 2.2.21 to 2.3.0
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.2.21...v2.3.0)

Updates `org.jetbrains.kotlin.plugin.serialization` from 2.2.21 to 2.3.0
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.2.21...v2.3.0)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin.jvm
  dependency-version: 2.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.jetbrains.kotlin.plugin.serialization
  dependency-version: 2.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-17 19:27:59 +08:00
dependabot[bot]
2327c5fd48 chore(deps): bump org.apache.commons:commons-pool2 from 2.12.1 to 2.13.0
Bumps org.apache.commons:commons-pool2 from 2.12.1 to 2.13.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-pool2
  dependency-version: 2.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 07:55:39 +08:00
Srar
bfc63a3983 fix: copy hotkey conflicts with ctrlc
(cherry picked from commit b499667cbb)
2025-12-12 09:32:32 +08:00
dependabot[bot]
c727925791 chore(deps): bump com.fasterxml.uuid:java-uuid-generator
Bumps [com.fasterxml.uuid:java-uuid-generator](https://github.com/cowtowncoder/java-uuid-generator) from 5.1.1 to 5.2.0.
- [Commits](https://github.com/cowtowncoder/java-uuid-generator/compare/java-uuid-generator-5.1.1...java-uuid-generator-5.2.0)

---
updated-dependencies:
- dependency-name: com.fasterxml.uuid:java-uuid-generator
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-12 09:27:41 +08:00
dependabot[bot]
cae1173180 chore(deps): bump flatlaf from 3.6.2 to 3.7
Bumps `flatlaf` from 3.6.2 to 3.7.

Updates `com.formdev:flatlaf` from 3.6.2 to 3.7
- [Release notes](https://github.com/JFormDesigner/FlatLaf/releases)
- [Changelog](https://github.com/JFormDesigner/FlatLaf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/JFormDesigner/FlatLaf/compare/3.6.2...3.7)

Updates `com.formdev:flatlaf-extras` from 3.6.2 to 3.7
- [Release notes](https://github.com/JFormDesigner/FlatLaf/releases)
- [Changelog](https://github.com/JFormDesigner/FlatLaf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/JFormDesigner/FlatLaf/compare/3.6.2...3.7)

Updates `com.formdev:flatlaf-swingx` from 3.6.2 to 3.7
- [Release notes](https://github.com/JFormDesigner/FlatLaf/releases)
- [Changelog](https://github.com/JFormDesigner/FlatLaf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/JFormDesigner/FlatLaf/compare/3.6.2...3.7)

---
updated-dependencies:
- dependency-name: com.formdev:flatlaf
  dependency-version: '3.7'
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: com.formdev:flatlaf-extras
  dependency-version: '3.7'
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: com.formdev:flatlaf-swingx
  dependency-version: '3.7'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-12 09:27:29 +08:00
dependabot[bot]
10d2736232 chore(deps): bump commons-io:commons-io from 2.20.0 to 2.21.0
Bumps [commons-io:commons-io](https://github.com/apache/commons-io) from 2.20.0 to 2.21.0.
- [Changelog](https://github.com/apache/commons-io/blob/master/RELEASE-NOTES.txt)
- [Commits](https://github.com/apache/commons-io/compare/rel/commons-io-2.20.0...rel/commons-io-2.21.0)

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-version: 2.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 14:37:56 +08:00
dependabot[bot]
97f01b7e3f chore(deps): bump org.apache.commons:commons-text from 1.14.0 to 1.15.0
Bumps [org.apache.commons:commons-text](https://github.com/apache/commons-text) from 1.14.0 to 1.15.0.
- [Changelog](https://github.com/apache/commons-text/blob/master/RELEASE-NOTES.txt)
- [Commits](https://github.com/apache/commons-text/compare/rel/commons-text-1.14.0...rel/commons-text-1.15.0)

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-text
  dependency-version: 1.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 14:37:42 +08:00
hstyi
21c7dd7a42 fix: prevent pulling changes for locally managed accounts 2025-12-08 16:26:24 +08:00
hstyi
bbc64043ed fix: correct scrolling region handling in ControlSequenceIntroducerProcessor 2025-12-08 16:26:15 +08:00
dependabot[bot]
79842f4625 chore(deps): bump exposed from 1.0.0-rc-2 to 1.0.0-rc-4
Bumps `exposed` from 1.0.0-rc-2 to 1.0.0-rc-4.

Updates `org.jetbrains.exposed:exposed-core` from 1.0.0-rc-2 to 1.0.0-rc-4
- [Release notes](https://github.com/JetBrains/Exposed/releases)
- [Changelog](https://github.com/JetBrains/Exposed/blob/main/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/Exposed/compare/1.0.0-rc-2...1.0.0-rc-4)

Updates `org.jetbrains.exposed:exposed-crypt` from 1.0.0-rc-2 to 1.0.0-rc-4
- [Release notes](https://github.com/JetBrains/Exposed/releases)
- [Changelog](https://github.com/JetBrains/Exposed/blob/main/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/Exposed/compare/1.0.0-rc-2...1.0.0-rc-4)

Updates `org.jetbrains.exposed:exposed-jdbc` from 1.0.0-rc-2 to 1.0.0-rc-4
- [Release notes](https://github.com/JetBrains/Exposed/releases)
- [Changelog](https://github.com/JetBrains/Exposed/blob/main/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/Exposed/compare/1.0.0-rc-2...1.0.0-rc-4)

Updates `org.jetbrains.exposed:exposed-migration-core` from 1.0.0-rc-2 to 1.0.0-rc-4
- [Release notes](https://github.com/JetBrains/Exposed/releases)
- [Changelog](https://github.com/JetBrains/Exposed/blob/main/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/Exposed/compare/1.0.0-rc-2...1.0.0-rc-4)

---
updated-dependencies:
- dependency-name: org.jetbrains.exposed:exposed-core
  dependency-version: 1.0.0-rc-4
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.exposed:exposed-crypt
  dependency-version: 1.0.0-rc-4
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.exposed:exposed-jdbc
  dependency-version: 1.0.0-rc-4
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.exposed:exposed-migration-core
  dependency-version: 1.0.0-rc-4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-04 08:49:46 +08:00
hstyi
626b344088 fix: ensure dialog title is set correctly in KeyboardInteractiveDialog 2025-11-30 12:21:09 +08:00
dependabot[bot]
5b165ed587 chore(deps): bump com.maxmind.geoip2:geoip2 from 4.4.0 to 5.0.0
Bumps [com.maxmind.geoip2:geoip2](https://github.com/maxmind/GeoIP2-java) from 4.4.0 to 5.0.0.
- [Release notes](https://github.com/maxmind/GeoIP2-java/releases)
- [Changelog](https://github.com/maxmind/GeoIP2-java/blob/main/CHANGELOG.md)
- [Commits](https://github.com/maxmind/GeoIP2-java/compare/v4.4.0...v5.0.0)

---
updated-dependencies:
- dependency-name: com.maxmind.geoip2:geoip2
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 18:16:48 +08:00
dependabot[bot]
d73b3b706e chore(deps): bump com.qcloud:cos_api from 5.6.257 to 5.6.259
Bumps [com.qcloud:cos_api](https://github.com/tencentyun/cos-java-sdk-v5) from 5.6.257 to 5.6.259.
- [Release notes](https://github.com/tencentyun/cos-java-sdk-v5/releases)
- [Changelog](https://github.com/tencentyun/cos-java-sdk-v5/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tencentyun/cos-java-sdk-v5/commits)

---
updated-dependencies:
- dependency-name: com.qcloud:cos_api
  dependency-version: 5.6.259
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-22 07:04:52 +08:00
dependabot[bot]
2928b35585 chore(deps): bump org.apache.commons:commons-lang3 from 3.19.0 to 3.20.0
Bumps org.apache.commons:commons-lang3 from 3.19.0 to 3.20.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-19 09:04:14 +08:00
hstyi
04bece21ff feat: insert new terminal tab at the correct index in terminal tab manager 2025-11-17 08:12:55 +08:00
hstyi
9e2e104baa chore: enhance terminal tab closing behavior to support reconnect option 2025-11-13 09:32:36 +08:00
hstyi
0615378a17 fix: selected terminal tab when transferring to a host 2025-11-11 10:52:28 +08:00
dependabot[bot]
013b03f9ef chore(deps): bump commons-codec:commons-codec from 1.19.0 to 1.20.0
Bumps [commons-codec:commons-codec](https://github.com/apache/commons-codec) from 1.19.0 to 1.20.0.
- [Changelog](https://github.com/apache/commons-codec/blob/master/RELEASE-NOTES.txt)
- [Commits](https://github.com/apache/commons-codec/compare/rel/commons-codec-1.19.0...rel/commons-codec-1.20.0)

---
updated-dependencies:
- dependency-name: commons-codec:commons-codec
  dependency-version: 1.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 10:17:06 +08:00
hstyi
026b13ba05 feat: add support for UI scaling via TERMORA_SCALE environment variable 2025-11-07 09:59:37 +08:00
dependabot[bot]
6ec526eeeb chore(deps): bump com.fazecast:jSerialComm from 2.11.2 to 2.11.4
Bumps [com.fazecast:jSerialComm](https://github.com/Fazecast/jSerialComm) from 2.11.2 to 2.11.4.
- [Release notes](https://github.com/Fazecast/jSerialComm/releases)
- [Commits](https://github.com/Fazecast/jSerialComm/commits)

---
updated-dependencies:
- dependency-name: com.fazecast:jSerialComm
  dependency-version: 2.11.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-04 11:00:57 +08:00
dependabot[bot]
e064bb9bb5 chore(deps): bump com.github.hstyi:geolite2
Bumps [com.github.hstyi:geolite2](https://github.com/hstyi/GeoLite2) from v1.0-202510200054 to v1.0-202510270056.
- [Release notes](https://github.com/hstyi/GeoLite2/releases)
- [Commits](https://github.com/hstyi/GeoLite2/commits)

---
updated-dependencies:
- dependency-name: com.github.hstyi:geolite2
  dependency-version: v1.0-202510270056
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 15:58:19 +08:00
dependabot[bot]
1f3fb5e2c0 chore(deps): bump okhttp from 5.2.1 to 5.3.0
Bumps `okhttp` from 5.2.1 to 5.3.0.

Updates `com.squareup.okhttp3:okhttp` from 5.2.1 to 5.3.0
- [Changelog](https://github.com/square/okhttp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/square/okhttp/compare/parent-5.2.1...parent-5.3.0)

Updates `com.squareup.okhttp3:logging-interceptor` from 5.2.1 to 5.3.0
- [Changelog](https://github.com/square/okhttp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/square/okhttp/compare/parent-5.2.1...parent-5.3.0)

---
updated-dependencies:
- dependency-name: com.squareup.okhttp3:okhttp
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: com.squareup.okhttp3:logging-interceptor
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 10:37:23 +08:00
hstyi
5984f3e856 chore: update JBR version to 21.0.8-b1163.69 2025-11-03 10:24:58 +08:00
34 changed files with 676 additions and 66 deletions

View File

@@ -4,7 +4,7 @@ on: [ push, pull_request ]
env: env:
JBR_MAJOR: 21.0.8 JBR_MAJOR: 21.0.8
JBR_PATCH: b1138.52 JBR_PATCH: b1163.69
jobs: jobs:
build: build:

View File

@@ -9,14 +9,14 @@ env:
TERMORA_MAC_NOTARY: "${{ startsWith(github.event.head_commit.message, 'release: ') && github.repository == 'TermoraDev/termora' }}" TERMORA_MAC_NOTARY: "${{ startsWith(github.event.head_commit.message, 'release: ') && github.repository == 'TermoraDev/termora' }}"
TERMORA_MAC_NOTARY_KEYCHAIN_PROFILE: ${{ secrets.TERMORA_MAC_NOTARY_KEYCHAIN_PROFILE }} TERMORA_MAC_NOTARY_KEYCHAIN_PROFILE: ${{ secrets.TERMORA_MAC_NOTARY_KEYCHAIN_PROFILE }}
JBR_MAJOR: 21.0.8 JBR_MAJOR: 21.0.8
JBR_PATCH: b1138.52 JBR_PATCH: b1163.69
jobs: jobs:
build: build:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ macos-15, macos-13 ] os: [ macos-15-intel, macos-latest ]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:

View File

@@ -4,7 +4,7 @@ on: [ push, pull_request ]
env: env:
JBR_MAJOR: 21.0.8 JBR_MAJOR: 21.0.8
JBR_PATCH: b1138.52 JBR_PATCH: b1163.69
jobs: jobs:
build: build:

View File

@@ -1,5 +1,5 @@
<div align="center"> <div align="center">
<a href="./README.zh_CN.md">简体中文</a> <a href="./README.zh_CN.md">简体中文</a> | <a href="./README.pt_BR.md">Português (Brasil)</a>
</div> </div>
# Termora # Termora

90
README.pt_BR.md Normal file
View File

@@ -0,0 +1,90 @@
<div align="center">
<a href="./README.md">English</a> | <a href="./README.zh_CN.md">简体中文</a>
</div>
# Termora
**Termora** é um emulador de terminal e cliente SSH multiplataforma, disponível para **Windows, macOS e Linux**.
<div align="center">
<img src="docs/readme.png" alt="Termora" />
</div>
O Termora é desenvolvido utilizando [**Kotlin/JVM**](https://kotlinlang.org/) e implementa parcialmente o [**protocolo de sequência de controle XTerm**](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html). Seu objetivo de longo prazo é alcançar **suporte total a plataformas** (incluindo Android, iOS e iPadOS) via [**Kotlin Multiplatform**](https://kotlinlang.org/docs/multiplatform.html).
## ✨ Recursos
- 🧬 Suporte multiplataforma
- 🔐 Gerenciador de chaves integrado
- 🖼️ Encaminhamento X11 (X11 forwarding)
- 🧑‍💻 Integração com SSH-Agent
- 💻 Exibição de informações do sistema
- 📁 Gerenciamento de arquivos SFTP via interface gráfica (GUI)
- 📊 Monitoramento de uso de GPU Nvidia
- ⚡ Atalhos de comandos rápidos
## 🚀 Transferência de Arquivos
- Transferências diretas entre servidor A ↔ B
- Suporte a pastas recursivas
- Até **6 tarefas de transferência simultâneas**
<div align="center">
<img src="docs/transfer.png" alt="Transferência" />
</div>
## 📝 Edição de Arquivos
- Upload automático após editar e salvar
- Renomear arquivos e pastas
- Exclusão rápida de pastas grandes (suporte a `rm -rf`)
- Edição visual de permissões
- Criação de novos arquivos e pastas
<div align="center">
<img src="docs/transfer-edit.png" alt="Edição de Arquivos" />
</div>
## 💻 Hosts
- Estrutura hierárquica em árvore, semelhante a pastas
- Atribuição de tags para hosts individuais
- Importação de hosts de outras ferramentas
- Abertura direta com a ferramenta de transferência
<div align="center">
<img src="docs/host.png" alt="Gerenciamento de Hosts" />
</div>
## 🧩 Plugins
- 🌍 Geo: Exibe a geolocalização dos hosts
- 🔄 Sync: Sincroniza configurações para Gist ou WebDAV
- 🗂️ WebDAV: Conecta a armazenamentos WebDAV
- 📝 Editor: Editor de arquivos SFTP integrado
- 📡 SMB: Conecta ao [SMB](https://pt.wikipedia.org/wiki/Server_Message_Block)
- ☁️ S3: Conecta ao armazenamento de objetos S3
- ☁️ Huawei OBS: Conecta ao Huawei Cloud OBS
- ☁️ Tencent COS: Conecta ao Tencent Cloud COS
- ☁️ Alibaba OSS: Conecta ao Alibaba Cloud OSS
- 👉 [Ver todos os plugins...](https://www.termora.app/plugins)
## 📦 Download
- 🧾 [Último Lançamento (Release)](https://github.com/TermoraDev/termora/releases/latest)
- 🍺 **Homebrew**: `brew install --cask termora`
- 🔨 **WinGet**: `winget install termora`
- <img src="https://apps.microsoft.com/assets/icons/logo-16x16.png" alt="microsoft logo"/> <b>Microsoft Store</b>: <a href="https://apps.microsoft.com/store/detail/9NRZBHG43SB9?cid=DevShareMCLPCS">Visite o Termora na Microsoft Store</a>
## 🛠️ Desenvolvimento
Recomendamos o uso do JDK [JetBrainsRuntime](https://github.com/JetBrains/JetBrainsRuntime) para o desenvolvimento.
- Executar localmente: `./gradlew :run`
## 📄 Licença
Este software é distribuído sob um modelo de licença dupla. Você pode escolher uma das seguintes opções:
- **AGPL-3.0**: Use, distribua e modifique o software sob os termos da [AGPL-3.0](https://opensource.org/license/agpl-v3).
- **Licença Proprietária**: Para uso em código fechado ou comercial, entre em contato com o autor para obter uma licença comercial.

View File

@@ -1,16 +1,16 @@
[versions] [versions]
kotlin = "2.2.21" kotlin = "2.3.0"
slf4j = "2.0.17" slf4j = "2.0.17"
pty4j = "0.13.10" pty4j = "0.13.10"
tinylog = "2.7.0" tinylog = "2.7.0"
kotlinx-coroutines = "1.10.2" kotlinx-coroutines = "1.10.2"
flatlaf = "3.6.2" flatlaf = "3.7"
kotlinx-serialization-json = "1.9.0" kotlinx-serialization-json = "1.9.0"
commons-codec = "1.19.0" commons-codec = "1.20.0"
commons-lang3 = "3.19.0" commons-lang3 = "3.20.0"
commons-csv = "1.14.1" commons-csv = "1.14.1"
commons-net = "3.12.0" commons-net = "3.12.0"
commons-text = "1.14.0" commons-text = "1.15.0"
commons-compress = "1.28.0" commons-compress = "1.28.0"
commons-vfs2 = "2.10.0" commons-vfs2 = "2.10.0"
swingx = "1.6.5-1" swingx = "1.6.5-1"
@@ -20,11 +20,11 @@ oshi = "6.9.1"
versioncompare = "1.4.1" versioncompare = "1.4.1"
jna = "5.18.1" jna = "5.18.1"
jSystemThemeDetector = "3.9.1" jSystemThemeDetector = "3.9.1"
commons-io = "2.20.0" commons-io = "2.21.0"
jbr-api = "17.1.10.1" jbr-api = "17.1.10.1"
hutool = "5.8.40" hutool = "5.8.40"
jsch = "2.27.3" jsch = "2.27.3"
okhttp = "5.2.1" okhttp = "5.3.0"
sshj = "0.39.0" sshj = "0.39.0"
sshd-core = "2.15.0" sshd-core = "2.15.0"
jgit = "7.4.0.202509020913-r" jgit = "7.4.0.202509020913-r"
@@ -33,18 +33,18 @@ jnafilechooser = "1.1.2"
xodus = "2.0.1" xodus = "2.0.1"
bip39 = "1.0.9" bip39 = "1.0.9"
colorpicker = "2.0.1" colorpicker = "2.0.1"
rhino = "1.8.0" rhino = "1.9.0"
delight-rhino-sandbox = "0.2.1" delight-rhino-sandbox = "0.2.1"
testcontainers = "2.0.1" testcontainers = "2.0.3"
mixpanel = "1.5.4" mixpanel = "1.7.0"
jSerialComm = "2.11.2" jSerialComm = "2.11.4"
ini4j = "0.5.5-2" ini4j = "0.5.5-2"
restart4j = "0.0.1" restart4j = "0.0.1"
eddsa = "0.3.0" eddsa = "0.3.0"
exposed = "1.0.0-rc-2" exposed = "1.0.0-rc-4"
h2 = "2.3.232" h2 = "2.3.232"
sqlite = "3.50.3.0" sqlite = "3.50.3.0"
jug = "5.1.1" jug = "5.2.0"
semver4j = "6.0.0" semver4j = "6.0.0"
jsvg = "2.0.0" jsvg = "2.0.0"
dom4j = "2.2.0" dom4j = "2.2.0"

View File

@@ -8,7 +8,7 @@ project.version = "0.0.4"
dependencies { dependencies {
testImplementation(kotlin("test")) testImplementation(kotlin("test"))
implementation("com.qcloud:cos_api:5.6.257") implementation("com.qcloud:cos_api:5.6.260.1")
compileOnly(project(":")) compileOnly(project(":"))
} }

View File

@@ -10,7 +10,7 @@ project.version = "0.0.8"
dependencies { dependencies {
testImplementation(kotlin("test")) testImplementation(kotlin("test"))
compileOnly(project(":")) compileOnly(project(":"))
implementation("com.fifesoft:rsyntaxtextarea:3.6.0") implementation("com.fifesoft:rsyntaxtextarea:3.6.1")
implementation("com.fifesoft:languagesupport:3.4.0") implementation("com.fifesoft:languagesupport:3.4.0")
implementation("com.fifesoft:autocomplete:3.3.2") implementation("com.fifesoft:autocomplete:3.3.2")
} }

View File

@@ -7,7 +7,7 @@ project.version = "0.0.2"
dependencies { dependencies {
testImplementation(kotlin("test")) testImplementation(kotlin("test"))
compileOnly(project(":")) compileOnly(project(":"))
implementation("org.apache.commons:commons-pool2:2.12.1") implementation("org.apache.commons:commons-pool2:2.13.0")
testImplementation(project(":")) testImplementation(project(":"))
} }

View File

@@ -7,9 +7,9 @@ project.version = "0.0.8"
dependencies { dependencies {
testImplementation(kotlin("test")) testImplementation(kotlin("test"))
compileOnly(project(":")) compileOnly(project(":"))
implementation("com.maxmind.geoip2:geoip2:4.4.0") implementation("com.maxmind.geoip2:geoip2:5.0.0")
// https://github.com/hstyi/geolite2 // https://github.com/hstyi/geolite2
implementation("com.github.hstyi:geolite2:v1.0-202510200054") implementation("com.github.hstyi:geolite2:v1.0-202510270056")
} }
apply(from = "$rootDir/plugins/common.gradle.kts") apply(from = "$rootDir/plugins/common.gradle.kts")

View File

@@ -10,7 +10,7 @@ project.version = "0.0.5"
dependencies { dependencies {
testImplementation(kotlin("test")) testImplementation(kotlin("test"))
compileOnly(project(":")) compileOnly(project(":"))
implementation("com.fazecast:jSerialComm:2.11.2") implementation("com.fazecast:jSerialComm:2.11.4")
} }
apply(from = "$rootDir/plugins/common.gradle.kts") apply(from = "$rootDir/plugins/common.gradle.kts")

View File

@@ -50,6 +50,17 @@ class ApplicationInitializr {
} }
} }
// https://github.com/TermoraDev/termora/issues/1254
if (System.getProperty(FlatSystemProperties.UI_SCALE).isNullOrBlank()) {
val scale = System.getenv("TERMORA_SCALE")
if (scale.isNullOrBlank().not()) {
if (NumberUtils.toDouble(scale, -1.0) > 0) {
System.setProperty(FlatSystemProperties.UI_SCALE_ENABLED, "true")
System.setProperty(FlatSystemProperties.UI_SCALE, scale)
}
}
}
// 启动 // 启动
val runtime = measureTimeMillis { ApplicationRunner().run() } val runtime = measureTimeMillis { ApplicationRunner().run() }
val log = LoggerFactory.getLogger(javaClass) val log = LoggerFactory.getLogger(javaClass)

View File

@@ -21,6 +21,7 @@ object I18n : AbstractI18n() {
"zh_CN" to "简体中文", "zh_CN" to "简体中文",
"zh_TW" to "繁體中文", "zh_TW" to "繁體中文",
"ru_RU" to "Русский", "ru_RU" to "Русский",
"pt_BR" to "Português",
) )
fun containsLanguage(locale: Locale): String? { fun containsLanguage(locale: Locale): String? {

View File

@@ -3,5 +3,5 @@ package app.termora
import app.termora.actions.AnActionEvent import app.termora.actions.AnActionEvent
import java.util.* import java.util.*
class OpenHostActionEvent(source: Any, val host: Host, event: EventObject) : class OpenHostActionEvent(source: Any, val host: Host, event: EventObject, val tabIndex: Int = -1) :
AnActionEvent(source, String(), event) AnActionEvent(source, String(), event)

View File

@@ -179,7 +179,7 @@ abstract class PtyHostTerminalTab(
val tab = createReconnectTerminalTab() val tab = createReconnectTerminalTab()
manager.addTerminalTab(index, tab, true) manager.addTerminalTab(index, tab, true)
manager.closeTerminalTab(this, true) manager.closeTerminalTab(this, disposable = true, reconnect = true)
if (tab is HostTerminalTab) { if (tab is HostTerminalTab) {
tab.start() tab.start()

View File

@@ -547,6 +547,7 @@ class SettingsOptionsPane : OptionsPane() {
rightClickComboBox.addItem("Copy") rightClickComboBox.addItem("Copy")
rightClickComboBox.addItem("CopyAndPaste") rightClickComboBox.addItem("CopyAndPaste")
rightClickComboBox.addItem("Nothing")
rightClickComboBox.selectedItem = terminalSetting.rightClick rightClickComboBox.selectedItem = terminalSetting.rightClick
@@ -576,6 +577,8 @@ class SettingsOptionsPane : OptionsPane() {
text = I18n.getString("termora.settings.terminal.right-click.copy") text = I18n.getString("termora.settings.terminal.right-click.copy")
} else if (value == "CopyAndPaste") { } else if (value == "CopyAndPaste") {
text = I18n.getString("termora.settings.terminal.right-click.copy-and-paste") text = I18n.getString("termora.settings.terminal.right-click.copy-and-paste")
}else if (value == "Nothing") {
text = I18n.getString("termora.settings.terminal.right-click.nothing")
} }
return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus) return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus)
} }

View File

@@ -141,12 +141,14 @@ class TerminalTabbed(
} }
private fun removeTabAt(index: Int, disposable: Boolean = true) { private fun removeTabAt(index: Int, disposable: Boolean = true, reconnect: Boolean = false) {
if (tabbedPane.isTabClosable(index)) { if (tabbedPane.isTabClosable(index)) {
val tab = tabs[index] val tab = tabs[index]
// 询问是否可以关闭 // 询问是否可以关闭
if (disposable) { if (disposable) {
// 如果是重连接,那么直接关闭不进行任何形式的询问
if (reconnect.not()) {
// 如果开启了关闭确认,那么直接询问用户 // 如果开启了关闭确认,那么直接询问用户
if (appearance.confirmTabClose) { if (appearance.confirmTabClose) {
if (OptionPane.showConfirmDialog( if (OptionPane.showConfirmDialog(
@@ -162,6 +164,7 @@ class TerminalTabbed(
return return
} }
} }
}
// 通知即将关闭 // 通知即将关闭
if (disposable) { if (disposable) {
@@ -233,7 +236,7 @@ class TerminalTabbed(
if (tab is HostTerminalTab) { if (tab is HostTerminalTab) {
actionManager actionManager
.getAction(OpenHostAction.OPEN_HOST) .getAction(OpenHostAction.OPEN_HOST)
.actionPerformed(OpenHostActionEvent(this, tab.host, evt)) .actionPerformed(OpenHostActionEvent(this, tab.host, evt, tabIndex + 1))
} }
} }
@@ -361,7 +364,7 @@ class TerminalTabbed(
} }
} }
override fun indexOfTerminalTab(tab: TerminalTab):Int { override fun indexOfTerminalTab(tab: TerminalTab): Int {
return tabbedPane.indexOfComponent(tab.getJComponent()) return tabbedPane.indexOfComponent(tab.getJComponent())
} }
@@ -451,10 +454,10 @@ class TerminalTabbed(
} }
} }
override fun closeTerminalTab(tab: TerminalTab, disposable: Boolean) { override fun closeTerminalTab(tab: TerminalTab, disposable: Boolean, reconnect: Boolean) {
for (i in 0 until tabs.size) { for (i in 0 until tabs.size) {
if (tabs[i] == tab) { if (tabs[i] == tab) {
removeTabAt(i, disposable) removeTabAt(i, disposable, reconnect)
break break
} }
} }

View File

@@ -6,7 +6,7 @@ interface TerminalTabbedManager {
fun getSelectedTerminalTab(): TerminalTab? fun getSelectedTerminalTab(): TerminalTab?
fun getTerminalTabs(): List<TerminalTab> fun getTerminalTabs(): List<TerminalTab>
fun setSelectedTerminalTab(tab: TerminalTab) fun setSelectedTerminalTab(tab: TerminalTab)
fun closeTerminalTab(tab: TerminalTab, disposable: Boolean = true) fun closeTerminalTab(tab: TerminalTab, disposable: Boolean = true, reconnect: Boolean = false)
fun refreshTerminalTabs() fun refreshTerminalTabs()
fun indexOfTerminalTab(tab: TerminalTab): Int fun indexOfTerminalTab(tab: TerminalTab): Int
} }

View File

@@ -67,6 +67,11 @@ class PullService private constructor() : SyncService(), Disposable, Application
private var lastChangeHash = StringUtils.EMPTY private var lastChangeHash = StringUtils.EMPTY
private fun pullChanges() { private fun pullChanges() {
if (accountManager.isLocally()) {
return
}
val hash: String val hash: String
try { try {

View File

@@ -56,7 +56,12 @@ class OpenHostAction : AnAction() {
if (tab == null) return if (tab == null) return
if (evt.tabIndex >= 0) {
terminalTabbedManager.addTerminalTab(evt.tabIndex, tab)
} else {
terminalTabbedManager.addTerminalTab(tab) terminalTabbedManager.addTerminalTab(tab)
}
if (tab is PtyHostTerminalTab) { if (tab is PtyHostTerminalTab) {
tab.start() tab.start()
} }

View File

@@ -20,6 +20,10 @@ class TerminalCopyAction : AnAction() {
override fun actionPerformed(evt: AnActionEvent) { override fun actionPerformed(evt: AnActionEvent) {
val terminalPanel = evt.getData(DataProviders.TerminalPanel) ?: return val terminalPanel = evt.getData(DataProviders.TerminalPanel) ?: return
val selectionModel = terminalPanel.terminal.getSelectionModel()
if (!selectionModel.hasSelection()) {
return
}
val text = terminalPanel.copy() val text = terminalPanel.copy()
val systemClipboard = terminalPanel.toolkit.systemClipboard val systemClipboard = terminalPanel.toolkit.systemClipboard

View File

@@ -27,12 +27,14 @@ class KeyboardInteractiveDialog(
isModal = true isModal = true
isResizable = true isResizable = true
controlsVisible = false controlsVisible = false
title = I18n.getString("termora.new-host.title")
init() init()
pack() pack()
size = Dimension(max(300, size.width), size.height) size = Dimension(max(300, size.width), size.height)
// fix https://github.com/TermoraDev/termora/issues/1311
pack()
setLocationRelativeTo(null) setLocationRelativeTo(null)
} }

View File

@@ -30,6 +30,7 @@ class TerminalUserInteraction(
) )
dialog.setLocationRelativeTo(owner) dialog.setLocationRelativeTo(owner)
dialog.title = instruction ?: name ?: "OTP" dialog.title = instruction ?: name ?: "OTP"
dialog.title = StringUtils.defaultIfBlank(dialog.title, "OTP")
passwords[i] = dialog.getText() passwords[i] = dialog.getText()
if (passwords[i].isBlank()) { if (passwords[i].isBlank()) {
break break

View File

@@ -10,6 +10,8 @@ import kotlinx.coroutines.launch
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import org.apache.commons.io.IOUtils import org.apache.commons.io.IOUtils
import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils
import org.apache.commons.lang3.Strings
import org.apache.commons.lang3.SystemUtils
import java.awt.datatransfer.DataFlavor import java.awt.datatransfer.DataFlavor
import java.awt.datatransfer.StringSelection import java.awt.datatransfer.StringSelection
import java.net.URI import java.net.URI
@@ -64,7 +66,15 @@ internal class RDPProtocolProvider private constructor() : GenericProtocolProvid
} }
val sb = StringBuilder() val sb = StringBuilder()
sb.append("full address:s:").append(host.host).append(':').append(host.port).appendLine() sb.append("full address:s:")
if (SystemUtils.IS_OS_WINDOWS && Strings.CI.contains(host.host, ":")) {
var newHost = Strings.CI.removeStart(host.host, "[")
newHost = Strings.CI.removeEnd(newHost, "]")
sb.append('[').append(newHost).append(']')
} else {
sb.append(host.host)
}
sb.append(':').append(host.port).appendLine()
sb.append("username:s:").append(host.username).appendLine() sb.append("username:s:").append(host.username).appendLine()
val desktop = host.options.extras["desktop"] val desktop = host.options.extras["desktop"]
if (desktop.isNullOrBlank().not()) { if (desktop.isNullOrBlank().not()) {

View File

@@ -27,9 +27,14 @@ class CloneSessionTerminalTabbedContextMenuExtension private constructor() : Ter
cloneSession.addActionListener(object : AnAction() { cloneSession.addActionListener(object : AnAction() {
override fun actionPerformed(evt: AnActionEvent) { override fun actionPerformed(evt: AnActionEvent) {
val terminalTabbedManager = evt.getData(DataProviders.TerminalTabbedManager) ?: return val terminalTabbedManager = evt.getData(DataProviders.TerminalTabbedManager) ?: return
val index = terminalTabbedManager.indexOfTerminalTab(tab)
val handler = c.copy(channel = null) val handler = c.copy(channel = null)
val newTab = SSHTerminalTab(windowScope, tab.host, handler) val newTab = SSHTerminalTab(windowScope, tab.host, handler)
if (index >= 0) {
terminalTabbedManager.addTerminalTab(index + 1, newTab)
} else {
terminalTabbedManager.addTerminalTab(newTab) terminalTabbedManager.addTerminalTab(newTab)
}
newTab.start() newTab.start()
} }
}) })

View File

@@ -332,6 +332,12 @@ class ControlSequenceIntroducerProcessor(terminal: Terminal, reader: TerminalRea
var top = sr.getOrElse(0) { 1 } var top = sr.getOrElse(0) { 1 }
var bottom = sr.getOrElse(1) { terminalModel.getRows() } var bottom = sr.getOrElse(1) { terminalModel.getRows() }
// ";r" https://vt100.net/docs/vt510-rm/DECSTBM.html
if (sr.size == 1 && args.startsWith(';')) {
bottom = top
top = 1
}
if (bottom <= top) { if (bottom <= top) {
if (log.isWarnEnabled) { if (log.isWarnEnabled) {
log.warn("Set Scrolling Region Error. top: $top , bottom: $bottom") log.warn("Set Scrolling Region Error. top: $top , bottom: $bottom")

View File

@@ -1,5 +1,6 @@
package app.termora.terminal.panel package app.termora.terminal.panel
import app.termora.actions.TerminalCopyAction
import app.termora.keymap.KeyShortcut import app.termora.keymap.KeyShortcut
import app.termora.keymap.KeymapManager import app.termora.keymap.KeymapManager
import app.termora.plugin.internal.AltKeyModifier import app.termora.plugin.internal.AltKeyModifier
@@ -71,6 +72,7 @@ class TerminalPanelKeyAdapter(
} }
val keyStroke = KeyStroke.getKeyStrokeForEvent(e) val keyStroke = KeyStroke.getKeyStrokeForEvent(e)
val keymapActions = activeKeymap.getActionIds(KeyShortcut(keyStroke))
for (action in terminalPanel.getTerminalActions()) { for (action in terminalPanel.getTerminalActions()) {
if (action.test(keyStroke, e)) { if (action.test(keyStroke, e)) {
action.actionPerformed(e) action.actionPerformed(e)
@@ -104,7 +106,9 @@ class TerminalPanelKeyAdapter(
} }
// 如果命中了全局快捷键,那么不处理 // 如果命中了全局快捷键,那么不处理
if (keyStroke.modifiers != 0 && activeKeymap.getActionIds(KeyShortcut(keyStroke)).isNotEmpty()) { val copyShortcutWithoutSelection =
keymapActions.contains(TerminalCopyAction.COPY) && terminal.getSelectionModel().hasSelection().not()
if (keyStroke.modifiers != 0 && keymapActions.isNotEmpty() && !copyShortcutWithoutSelection) {
return return
} }

View File

@@ -53,6 +53,7 @@ class TerminalPanelMouseSelectionAdapter(private val terminalPanel: TerminalPane
if (SwingUtilities.isRightMouseButton(e)) { if (SwingUtilities.isRightMouseButton(e)) {
// 如果有选中并且开启了选中复制,那么右键直接是粘贴 // 如果有选中并且开启了选中复制,那么右键直接是粘贴
if (selectionModel.hasSelection() && isSelectCopy.not()) { if (selectionModel.hasSelection() && isSelectCopy.not()) {
if (rightClickMode != "Nothing") {
triggerCopyAction( triggerCopyAction(
KeyEvent( KeyEvent(
e.component, e.component,
@@ -76,7 +77,7 @@ class TerminalPanelMouseSelectionAdapter(private val terminalPanel: TerminalPane
) )
) )
} }
}
} else { } else {
// paste // paste
triggerPasteAction( triggerPasteAction(

View File

@@ -46,6 +46,7 @@ class TransferAnAction : AnAction(I18n.getString("termora.transport.sftp"), Icon
val panel = tabbed.getTransportPanel(i) ?: continue val panel = tabbed.getTransportPanel(i) ?: continue
if (panel.host.id == host.id) { if (panel.host.id == host.id) {
tabbed.selectedIndex = i tabbed.selectedIndex = i
terminalTabbedManager.setSelectedTerminalTab(sftpTab)
return return
} }
} }

View File

@@ -59,6 +59,7 @@ termora.settings.terminal.hyperlink=Hyperlink
termora.settings.terminal.select-copy=Select copy termora.settings.terminal.select-copy=Select copy
termora.settings.terminal.right-click=Right click termora.settings.terminal.right-click=Right click
termora.settings.terminal.right-click.copy-and-paste=Copy and Paste termora.settings.terminal.right-click.copy-and-paste=Copy and Paste
termora.settings.terminal.right-click.nothing=Nothing
termora.settings.terminal.right-click.copy=${termora.copy} termora.settings.terminal.right-click.copy=${termora.copy}
termora.settings.terminal.cursor-style=Cursor type termora.settings.terminal.cursor-style=Cursor type
termora.settings.terminal.cursor-blink=Cursor blink termora.settings.terminal.cursor-blink=Cursor blink

View File

@@ -0,0 +1,454 @@
termora.title=Termora
termora.confirm=OK
termora.exit=Sair
termora.cancel=Cancelar
termora.copy=Copiar
termora.paste=Colar
termora.apply=Aplicar
termora.save=Salvar
termora.remove=Excluir
termora.yes=Sim
termora.no=Não
termora.date-format=dd/MM/yyyy HH:mm:ss
termora.finder=Localizador
termora.folder=Pasta
termora.file=Arquivo
termora.explorer=Explorador
termora.quit-confirm=Finalizar {0}?
termora.regex=Regex
termora.match-case=Diferenciar maiúsculas/minúsculas
termora.optional=Opcional
# update
termora.update.title=Nova versão
termora.update.update=Atualizar
# Hosts
termora.host.modified-server-key.title=A IDENTIFICAÇÃO DO HOST [{0}] MUDOU
termora.host.modified-server-key.thumbprint=Impressão digital (thumbprint) da chave do host
termora.host.modified-server-key.expected=Esperado
termora.host.modified-server-key.actual=Atual
termora.host.modified-server-key.are-you-sure=Tem certeza de que deseja continuar a conexão?
# Settings
termora.setting=Configurações
termora.settings.appearance=Geral
termora.settings.appearance.theme=Tema
termora.settings.appearance.layout=Layout
termora.settings.appearance.layout.screen=Tela
termora.settings.appearance.layout.fence=Divisão
termora.settings.appearance.language=Idioma
termora.settings.appearance.i-want-to-translate=Eu quero traduzir
termora.settings.appearance.follow-system=Sincronizar com o SO
termora.settings.appearance.opacity=Opacidade
termora.settings.appearance.background-running=Execução em segundo plano
termora.settings.appearance.tab-order=Ordem das Abas
termora.settings.appearance.confirm-tab-close=Confirmar fechamento de aba
termora.settings.terminal=Terminal
termora.settings.terminal.font=Fonte
termora.settings.terminal.fallback-font=Fonte de Reserva
termora.settings.terminal.size=Tamanho
termora.settings.terminal.max-rows=Máximo de linhas
termora.settings.terminal.debug=Modo de depuração
termora.settings.terminal.beep=Bipe
termora.settings.terminal.hyperlink=Link
termora.settings.terminal.select-copy=Copiar ao selecionar
termora.settings.terminal.right-click=Clique com o botão direito
termora.settings.terminal.right-click.copy-and-paste=Copiar e Colar
termora.settings.terminal.right-click.nothing=Nada
termora.settings.terminal.right-click.copy=${termora.copy}
termora.settings.terminal.cursor-style=Tipo de cursor
termora.settings.terminal.cursor-blink=Cursor piscante
termora.settings.terminal.local-shell=Shell local
termora.settings.terminal.floating-toolbar=Barra de Ferramentas Flutuante
termora.settings.terminal.auto-close-tab=Fechar Aba Automaticamente
termora.settings.terminal.auto-close-tab-description=Fechar automaticamente a aba quando o terminal for desconectado normalmente
termora.settings.about=Sobre
termora.settings.about.author=Autor
termora.settings.about.source=Código-fonte
termora.settings.about.issue=Problemas (Issues)
termora.settings.about.third-party=Terceiros
termora.settings.about.termora=<html><b>${termora.title}</b> ({0}) é um cliente SSH multiplataforma. </html>
termora.settings.plugin=Plugins
termora.settings.plugin.install=Instalar
termora.settings.plugin.installed=Instalado
termora.settings.plugin.marketplace=Marketplace
termora.settings.plugin.uninstall=Desinstalar
termora.settings.plugin.uninstall-confirm=Tem certeza de que deseja desinstalar <b>{0}</b>?
termora.settings.plugin.uninstall-failed=Falha na desinstalação
termora.settings.plugin.install-failed=Falha na instalação, tente novamente mais tarde
termora.settings.plugin.install-from-disk=Instalar Plugin do Disco...
termora.settings.plugin.manage-plugin-repository=Gerenciar Repositório de Plugins...
termora.settings.plugin.install-from-disk-warning=O plugin <b>{0}</b> terá acesso a todos os seus dados. Tem certeza de que deseja instalá-lo?
termora.settings.plugin.not-compatible=O plugin <b>{0}</b> é incompatível com a versão atual. Por favor, reinstale <b>{0}</b>
termora.settings.account=Conta
termora.settings.account.login=Entrar
termora.settings.account.server=Servidor
termora.settings.account.wait-login=Aguardando login no navegador padrão...
termora.settings.account.locally=localmente
termora.settings.account.lifetime=Vitalício
termora.settings.account.upgrade=Upgrade
termora.settings.account.verify=Verificar
termora.settings.account.subscription=Assinatura
termora.settings.account.valid-to=Válido até
termora.settings.account.synchronization-on=Sincronização ativada
termora.settings.account.sync-now=Sincronizar agora
termora.settings.account.logout=Sair
termora.settings.account.logout-confirm=Tem certeza de que deseja sair?
termora.settings.account.unsynced-logout-confirm=Não sincronizado. Tem certeza de que deseja sair?
termora.settings.account.server-singapore=Cingapura
termora.settings.account.server-china=China Continental
termora.settings.account.new-server=Novo Servidor
termora.settings.account.deploy-server=Implantar
termora.settings.account.login-failed=Falha no login, tente novamente mais tarde
termora.settings.keymap=Atalhos de Teclado
termora.settings.keymap.shortcut=Atalho
termora.settings.keymap.action=Ação
termora.settings.keymap.already-exists=O atalho [{0}] já está em uso por [{1}]
termora.settings.keymap.question=Selecione uma linha e pressione a tecla <font color=rgb({0},{1},{2})> ⌫ (Backspace)</font> para remover o atalho
termora.settings.sftp.edit-command=Comando de Edição
termora.settings.sftp.db-click-behavior=Clique duplo
termora.settings.sftp.fixed-tab=Aba fixa
termora.settings.sftp.default-directory=Diretório Padrão
termora.settings.sftp.preserve-time=Preservar data de modificação original do arquivo
termora.settings.restart.title=Reiniciar
termora.settings.restart.message=As alterações terão efeito após reiniciar o aplicativo
termora.settings.restart.manually=Por favor, reinicie o software manualmente
# Find everywhere
termora.find-everywhere=Busca Global
termora.find-everywhere.search-for-something=Procurar por algo...
termora.find-everywhere.groups.quick-actions=Ações rápidas
termora.find-everywhere.groups.open-new-hosts=Abrir novo host
termora.find-everywhere.groups.opened-hosts=Hosts abertos
termora.find-everywhere.groups.tools=Ferramentas
termora.find-everywhere.groups.settings=${termora.setting}
termora.find-everywhere.quick-command.local-terminal=Terminal Local
# Welcome
termora.welcome.my-hosts=Meus hosts
termora.welcome.toggle-sidebar=Alternar Barra Lateral
termora.welcome.contextmenu.connect=Conectar
termora.welcome.contextmenu.connect-with=Conectar com
termora.welcome.contextmenu.open-in-new-window=${termora.tabbed.contextmenu.open-in-new-window}
termora.welcome.contextmenu.refresh=${termora.transport.table.contextmenu.refresh}
termora.welcome.contextmenu.copy=${termora.copy}
termora.welcome.contextmenu.remove=${termora.remove}
termora.welcome.contextmenu.rename=Renomear
termora.welcome.contextmenu.expand-all=Expandir tudo
termora.welcome.contextmenu.collapse-all=Recolher tudo
termora.welcome.contextmenu.new=Novo
termora.welcome.contextmenu.import=${termora.keymgr.import}
termora.welcome.contextmenu.new.folder=${termora.folder}
termora.welcome.contextmenu.new.host=Host
termora.welcome.contextmenu.new.folder.name=Nova Pasta
termora.welcome.contextmenu.property=Propriedades
termora.welcome.contextmenu.show=Mostrar
termora.welcome.contextmenu.show.more-info=Mais informações
termora.welcome.contextmenu.show.tags=${termora.tag}
termora.welcome.contextmenu.download=Download
termora.welcome.contextmenu.import.csv.download-template=Deseja importar ou baixar o modelo?
termora.welcome.contextmenu.import.csv.download-template-done=Modelo baixado com sucesso
termora.welcome.contextmenu.import.csv.download-template-done-open-folder=Modelo baixado com sucesso. Deseja abrir a pasta?
termora.welcome.contextmenu.import.xshell-folder-empty=A pasta não contém arquivos *.xsh. Por favor, selecione o diretório correto de Sessões do Xshell
termora.welcome.contextmenu.import.finalshell-folder-empty=A pasta não contém arquivos *_connect_config.json. Por favor, selecione o diretório correto do FinalShell
# New Host
termora.new-host.title=Criar um novo host
termora.new-host.general=Geral
termora.new-host.general.name=Nome
termora.new-host.general.protocol=Protocolo
termora.new-host.general.host=Host
termora.new-host.general.port=Porta
termora.new-host.general.username=Usuário
termora.new-host.general.authentication=Autenticação
termora.new-host.general.password=Senha
termora.new-host.general.remark=Comentário
termora.new-host.general.remember=Lembrar
termora.new-host.proxy=Proxy
termora.new-host.terminal=${termora.settings.terminal}
termora.new-host.terminal.encoding=Codificação
termora.new-host.terminal.backspace=Backspace
termora.new-host.terminal.character-mode=Um caractere por vez
termora.new-host.terminal.heartbeat-interval=Intervalo de Heartbeat
termora.new-host.terminal.timeout=Tempo limite
termora.new-host.terminal.startup-commands=Comando de Inicialização
termora.new-host.terminal.alt-modifier=Modificador Alt
termora.new-host.terminal.alt-modifier.eight-bit=Caracteres de 8 bits
termora.new-host.terminal.alt-modifier.by-esc=Caracteres precedidos por ESC
termora.new-host.terminal.env=Ambiente
termora.new-host.terminal.login-scripts=Scripts de Login
termora.new-host.terminal.expect=Expect
termora.new-host.terminal.send=Send
termora.new-host.serial=Serial
termora.new-host.serial.port=Porta
termora.new-host.serial.baud-rate=Baud rate
termora.new-host.serial.data-bits=Data bits
termora.new-host.serial.parity=Paridade
termora.new-host.serial.stop-bits=Stop bits
termora.new-host.serial.flow-control=Controle de fluxo
termora.new-host.tunneling=Túnel
termora.new-host.tunneling.table.name=Nome
termora.new-host.tunneling.table.type=Tipo
termora.new-host.tunneling.table.source=Origem
termora.new-host.tunneling.table.destination=Destino
termora.new-host.tunneling.add=Adicionar
termora.new-host.tunneling.edit=${termora.keymgr.edit}
termora.new-host.tunneling.delete=${termora.remove}
termora.new-host.rdp.desktop-placeholder=Tela cheia padrão (ex: 1920×1080)
termora.new-host.rdp.resolution=Resolução
termora.new-host.wsl.distribution=Nome da Distro
termora.new-host.test-connection=Testar Conexão
termora.new-host.test-connection-successful=Conexão bem-sucedida
termora.new-host.jump-hosts=Servidores de Salto
# Key manager
termora.keymgr.title=Gerenciador de Chaves
termora.keymgr.my-keys=Minhas chaves
termora.keymgr.generate=Gerar
termora.keymgr.import=Importar
termora.keymgr.export=Exportar
termora.keymgr.edit=Editar
termora.keymgr.private-key=Chave Privada
termora.keymgr.delete-warning=Tem certeza de que deseja excluir?
termora.keymgr.table.name=Nome
termora.keymgr.table.type=Tipo
termora.keymgr.table.length=Comprimento
termora.keymgr.table.remark=Descrição
termora.keymgr.export-done=A exportação foi concluída com sucesso
termora.keymgr.export-done-open-folder=A exportação foi concluída com sucesso. Deseja abrir a pasta?
termora.keymgr.ssh-copy-id.number=Número de hosts [{0}] Número de chaves públicas [{1}]
termora.keymgr.ssh-copy-id.successful=${termora.terminal.copied}
termora.keymgr.ssh-copy-id.failed=Falha ao copiar
termora.keymgr.ssh-copy-id.end=Fim da cópia da chave pública
# Tabbed
termora.tabbed.contextmenu.rename=Renomear
termora.tabbed.contextmenu.select-host=Selecionar Host
termora.tabbed.contextmenu.sftp-command=Comando SFTP
termora.tabbed.contextmenu.sftp-not-install=Programa SFTP não encontrado, instale e tente novamente
termora.tabbed.contextmenu.clone=Clonar
termora.tabbed.contextmenu.clone-session=Clonar Sessão
termora.tabbed.contextmenu.open-in-new-window=Abrir em Nova Janela
termora.tabbed.contextmenu.close=Fechar
termora.tabbed.contextmenu.close-other-tabs=Fechar Outras Abas
termora.tabbed.contextmenu.close-all-tabs=Fechar Todas as Abas
termora.tabbed.contextmenu.reconnect=Reconectar
termora.tabbed.local-tab.close-prompt=Deseja encerrar um processo em execução neste terminal?
termora.tabbed.tab.close-prompt=Tem certeza de que deseja fechar esta aba?
# Terminal logger
termora.terminal-logger=Log do Terminal
termora.terminal-logger.start-recording=Iniciar Gravação
termora.terminal-logger.plain-text=Texto sem formatação
termora.terminal-logger.styled-text=Texto formatado
termora.terminal-logger.stop-recording=Parar Gravação
termora.terminal-logger.open-log-viewer=Abrir Visualizador de Log
termora.terminal-logger.open-in-folder=Abrir em {0}
# Highlight
termora.highlight=Conjuntos de Realce
termora.highlight.default-set=Conjunto Padrão
termora.highlight.text-color=Cor do Texto
termora.highlight.background-color=Cor do Fundo
termora.highlight.keyword=Palavra-chave
termora.highlight.my-keyword=Minha Palavra-chave
termora.highlight.preview=Visualização
termora.highlight.description=Descrição
termora.highlight.bold=Negrito
termora.highlight.italic=Itálico
termora.highlight.underline=Sublinhado
termora.highlight.line-through=Tachado
# tag
termora.tag=Tags
termora.tag.my-tags=Minhas tags
termora.tag.manage-tags=Gerenciar tags
# Macro
termora.macro=Macros
termora.macro.start-recording=Iniciar Gravação
termora.macro.stop-recording=Parar Gravação
termora.macro.playback=Reproduzir
termora.macro.manager=Gerenciar Macros
termora.macro.run=Executar
# Snippets
termora.snippet=Snippet
termora.snippet.title=Snippets
# Tools
termora.tools.multiple=Enviar comando para as sessões da janela atual
# Transport
termora.transport.local=Local
termora.transport.file-already-exists=O arquivo {0} já existe
termora.transport.toolbar.prev=Voltar
termora.transport.toolbar.home=Pasta Pessoal (Home)
termora.transport.toolbar.next=Avançar
termora.transport.toolbar.parent=Pasta Superior
termora.transport.toolbar.show-hide=Mostrar/Ocultar Pastas
termora.transport.toolbar.refresh=Atualizar Pasta
termora.transport.bookmarks=Gerenciador de Favoritos
termora.transport.bookmarks.up=Para cima
termora.transport.bookmarks.down=Para baixo
termora.transport.table.filename=Nome do arquivo
termora.transport.table.type=Tipo
termora.transport.table.type.symbolic-link=Link Simbólico
termora.transport.table.size=Tamanho
termora.transport.table.modified-time=Modificado
termora.transport.table.permissions=Permissões
termora.transport.table.owner=Proprietário
# contextmenu
termora.transport.table.contextmenu.transfer=Transferir
termora.transport.table.contextmenu.edit=${termora.keymgr.edit}
termora.transport.table.contextmenu.copy-path=Copiar Caminho
termora.transport.table.contextmenu.open-in-folder=Abrir em {0}
termora.transport.table.contextmenu.rename=${termora.welcome.contextmenu.rename}
termora.transport.table.contextmenu.delete=${termora.remove}
termora.transport.table.contextmenu.rm-warning=Usar o comando rm -rf para excluir um arquivo é muito perigoso
termora.transport.table.contextmenu.change-permissions=Alterar Permissões...
termora.transport.table.contextmenu.refresh=Atualizar
termora.transport.table.contextmenu.compress=Compactar
termora.transport.table.contextmenu.extract=Extrair
termora.transport.table.contextmenu.extract.here=Extrair aqui
termora.transport.table.contextmenu.extract.single=Extrair para {0}\\
termora.transport.table.contextmenu.extract.multi=Extrair para *\\*
termora.transport.table.contextmenu.new=${termora.welcome.contextmenu.new}
termora.transport.table.contextmenu.new.folder=${termora.welcome.contextmenu.new.folder.name}
termora.transport.table.contextmenu.new.file=Novo Arquivo
# Permission
termora.transport.permissions=Alterar Permissões
termora.transport.permissions.file-folder-permissions=Permissões de Arquivo/Pasta
termora.transport.permissions.read=Leitura
termora.transport.permissions.write=Escrita
termora.transport.permissions.execute=Execução
termora.transport.permissions.owner=Proprietário
termora.transport.permissions.group=Grupo
termora.transport.permissions.others=Outros
termora.transport.permissions.include-subfolder=Incluir subdiretórios
termora.transport.sftp=Transferência
termora.transport.sftp.retry=Repetir
termora.transport.sftp.select-another-host=Selecionar outro host
termora.transport.sftp.select-host=Selecionar host
termora.transport.sftp.connecting=Conectando...
termora.transport.sftp.closed=A conexão foi fechada
termora.transport.sftp.close-tab=A transferência ainda está ativa. Tem certeza de que deseja remover todas as tarefas e fechar esta sessão?
termora.transport.sftp.close-tab-has-active-session=A sessão ainda está ativa. Deseja fechar todas as sessões?
termora.transport.sftp.status.transporting=Em progresso
termora.transport.sftp.status.deleting=Excluindo
termora.transport.sftp.status.waiting=Aguardando
termora.transport.sftp.status.done=Concluído
termora.transport.sftp.status.failed=Falhou
termora.transport.sftp.already-exists.message1=Esta pasta já contém um objeto com o nome abaixo
termora.transport.sftp.already-exists.message2=Selecione uma ação
termora.transport.sftp.already-exists.overwrite=Sobrescrever
termora.transport.sftp.already-exists.append=Anexar (Append)
termora.transport.sftp.already-exists.skip=Pular
termora.transport.sftp.already-exists.apply-all=Aplicar a todos
termora.transport.sftp.already-exists.name=Nome
termora.transport.sftp.already-exists.destination=Destino
termora.transport.sftp.already-exists.source=Origem
termora.transport.sftp.already-exists.actions=Ações
# transport job
termora.transport.jobs.table.name=Nome
termora.transport.jobs.table.status=Status
termora.transport.jobs.table.progress=Progresso
termora.transport.jobs.table.size=Tamanho
termora.transport.jobs.table.source-path=Caminho de Origem
termora.transport.jobs.table.target-path=Caminho de Destino
termora.transport.jobs.table.speed=Velocidade
termora.transport.jobs.table.estimated-time=Tempo estimado
termora.transport.jobs.table.estimated-time-days-format={0}d {1}h {2}m {3}s
termora.transport.jobs.table.estimated-time-hours-format={0}h {1}m {2}s
termora.transport.jobs.table.estimated-time-minutes-format={0}m {1}s
termora.transport.jobs.table.estimated-time-seconds-format={0}s
termora.transport.jobs.contextmenu.delete=${termora.remove}
termora.transport.jobs.contextmenu.delete-all=Excluir Todos
# ToolBar
termora.toolbar.customize-toolbar=Personalizar Barra de Ferramentas...
# Actions
termora.actions.copy-from-terminal=Copiar do Terminal
termora.actions.focus-mode=Modo Foco
termora.actions.paste-to-terminal=Colar no Terminal
termora.actions.select-all-in-terminal=Selecionar Tudo no Terminal
termora.actions.open-terminal-find=Abrir Busca no Terminal
termora.actions.close-tab=Fechar Aba
termora.actions.zoom-in-terminal=Aumentar Zoom do Terminal
termora.actions.zoom-out-terminal=Diminuir Zoom do Terminal
termora.actions.zoom-reset-terminal=Redefinir Zoom do Terminal
termora.actions.open-local-terminal=Abrir Terminal Local
termora.actions.quick-connect=Conexão Rápida
termora.actions.open-find-everywhere=Abrir Busca Global
termora.actions.open-new-window=Abrir nova Janela
termora.actions.clear-screen=Limpar Tela do Terminal
termora.actions.open-sftp-command=Abrir Comando SFTP
termora.actions.switch-tab=Alternar para Aba específica [1..9]
# Terminal
termora.terminal.size=Tamanho: {0} x {1}
termora.terminal.copied=Copiado
termora.terminal.channel-disconnected=O canal foi desconectado.\u0020
termora.terminal.channel-reconnect=Digite {0} para reconectar.
# protocol
termora.protocol.not-supported=O protocolo {0} não é suportado, você pode precisar instalar um plugin
# Visual Window
termora.visual-window.system-information=Informações do sistema
termora.visual-window.system-information.mem=Mem
termora.visual-window.system-information.swap=Swap
termora.visual-window.system-information.filesystem=Sist. Arquivos
termora.visual-window.system-information.used-total=Usado / Total
termora.visual-window.toggle-window=Alternar janela
termora.visual-window.transport.question=Mais recursos
termora.visual-window.nvidia-smi=NVIDIA SMI
termora.floating-toolbar.close-in-current-tab=Fechar na aba atual
# zmodem
termora.addons.zmodem.skip=PULAR

View File

@@ -81,6 +81,7 @@ termora.settings.terminal.hyperlink=Ссылки
termora.settings.terminal.select-copy=Копировать выделенное termora.settings.terminal.select-copy=Копировать выделенное
termora.settings.terminal.right-click=правой кнопкой мыши termora.settings.terminal.right-click=правой кнопкой мыши
termora.settings.terminal.right-click.copy-and-paste=Копировать и вставить termora.settings.terminal.right-click.copy-and-paste=Копировать и вставить
termora.settings.terminal.right-click.nothing=никто
termora.settings.terminal.cursor-style=Вид курсора termora.settings.terminal.cursor-style=Вид курсора
termora.settings.terminal.cursor-blink=Мигать курсором termora.settings.terminal.cursor-blink=Мигать курсором
termora.settings.terminal.local-shell=Локальный терминал termora.settings.terminal.local-shell=Локальный терминал

View File

@@ -73,6 +73,7 @@ termora.settings.terminal.hyperlink=超链接
termora.settings.terminal.select-copy=选中复制 termora.settings.terminal.select-copy=选中复制
termora.settings.terminal.right-click=右键点击 termora.settings.terminal.right-click=右键点击
termora.settings.terminal.right-click.copy-and-paste=复制 & 粘贴 termora.settings.terminal.right-click.copy-and-paste=复制 & 粘贴
termora.settings.terminal.right-click.nothing=无操作
termora.settings.terminal.cursor-style=光标样式 termora.settings.terminal.cursor-style=光标样式
termora.settings.terminal.cursor-blink=光标闪烁 termora.settings.terminal.cursor-blink=光标闪烁
termora.settings.terminal.local-shell=本地终端 termora.settings.terminal.local-shell=本地终端

View File

@@ -85,6 +85,7 @@ termora.settings.terminal.hyperlink=超連結
termora.settings.terminal.select-copy=選取複製 termora.settings.terminal.select-copy=選取複製
termora.settings.terminal.right-click=右鍵點擊 termora.settings.terminal.right-click=右鍵點擊
termora.settings.terminal.right-click.copy-and-paste=複製 & 貼上 termora.settings.terminal.right-click.copy-and-paste=複製 & 貼上
termora.settings.terminal.right-click.nothing=無操作
termora.settings.terminal.cursor-style=遊標風格 termora.settings.terminal.cursor-style=遊標風格
termora.settings.terminal.cursor-blink=遊標閃爍 termora.settings.terminal.cursor-blink=遊標閃爍
termora.settings.terminal.local-shell=本地端 termora.settings.terminal.local-shell=本地端