diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5069ff7f..a265aff73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,14 +131,24 @@ jobs: script: | core.setFailed('Pinning did not succeed') + # dnslink-dnsimple requires go + - uses: actions/setup-go@v4 + if: github.ref == 'refs/heads/main' + with: + go-version: "1.20.x" + + - name: Set up dnslink updater + if: github.ref == 'refs/heads/main' + run: go install github.com/ipfs/dnslink-dnsimple@v0.1.0 + # dev dnslink is updated on each main branch update - - run: npx dnslink-dnsimple --domain dev.webui.ipfs.io --link /ipfs/${{ steps.ipfs.outputs.cid }} + - run: dnslink-dnsimple --domain dev.webui.ipfs.io --record _dnslink --link /ipfs/${{ steps.ipfs.outputs.cid }} if: github.ref == 'refs/heads/main' env: DNSIMPLE_TOKEN: ${{ secrets.DNSIMPLE_TOKEN }} # production dnslink is updated on release (during tag build) - - run: npx dnslink-dnsimple --domain webui.ipfs.io --link /ipfs/${{ steps.ipfs.outputs.cid }} + - run: dnslink-dnsimple --domain webui.ipfs.io --record _dnslink --link /ipfs/${{ steps.ipfs.outputs.cid }} if: github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch' env: DNSIMPLE_TOKEN: ${{ secrets.DNSIMPLE_TOKEN }} diff --git a/README.md b/README.md index fb246d9d2..605a7df96 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # IPFS Web UI -> A web interface to [IPFS](https://ipfs.io), shipped with [Kubo](https://github.com/ipfs/kubo), and [ipfs-desktop](https://github.com/ipfs/ipfs-desktop/). +> A web interface to [IPFS](https://ipfs.tech), shipped with [Kubo](https://github.com/ipfs/kubo), and [ipfs-desktop](https://github.com/ipfs/ipfs-desktop/). > > Check on your node stats, explore the IPLD powered merkle forest, see peers around the world and manage your files, without needing to touch the CLI. diff --git a/public/locales/id/explore.json b/public/locales/id/explore.json index f245b4796..65725fc62 100644 --- a/public/locales/id/explore.json +++ b/public/locales/id/explore.json @@ -68,6 +68,6 @@ } }, "errors": { - "BlockFetchTimeoutError": "Failed to fetch content in {timeout}s. Please refresh the page to retry or try a different CID." + "BlockFetchTimeoutError": "Gagal mengambil konten dalam {timeout}s. Harap segarkan halaman untuk mencoba lagi atau mencoba CID lain." } } diff --git a/public/locales/ja-JP/app.json b/public/locales/ja-JP/app.json new file mode 100644 index 000000000..578686135 --- /dev/null +++ b/public/locales/ja-JP/app.json @@ -0,0 +1,106 @@ +{ + "actions": { + "add": "追加", + "apply": "適用", + "browse": "ブラウズ", + "cancel": "キャンセル", + "change": "変更", + "clear": "クリア", + "close": "閉じる", + "copy": "コピー", + "create": "作成", + "remove": "削除", + "download": "ダウンロード", + "edit": "編集", + "import": "インポート", + "inspect": "Inspect", + "more": "More", + "moreInfo": "より詳しい情報", + "noThanks": "拒否", + "ok": "了解", + "pinVerb": "ピン", + "rename": "名前を変更", + "reset": "リセット", + "save": "保存", + "saving": "保存中……", + "selectAll": "全て選択", + "setPinning": "ピンを設定", + "submit": "設定", + "unpin": "ピン解除", + "unselectAll": "選択を全て解除", + "generate": "生成", + "publish": "Publish", + "downloadCar": "CARをダウンロード", + "done": "終了" + }, + "cliModal": { + "description": "IPFSでのこの操作をコマンドライン上で行うには、以下をコピー&ペーストしてください。パラメータは適当なものに置き換えてください。" + }, + "nav": { + "bugsLink": "バグ報告", + "codeLink": "コードを見る" + }, + "status": { + "connectedToIpfs": "IPFSに接続完了", + "connectingToIpfs": "IPFSサービスに接続しています…", + "couldNotConnect": "IPFS API に接続できませんでした。" + }, + "apiAddressForm": { + "placeholder": "Enter a URL (http://127.0.0.1:5001) or a Multiaddr (/ip4/127.0.0.1/tcp/5001)" + }, + "publicGatewayForm": { + "placeholder": "URLを入力 (https://dweb.link)" + }, + "terms": { + "address": "アドレス", + "addresses": "アドレス", + "advanced": "詳細情報", + "agent": "Agent", + "api": "アプリケーションプログラミングインターフェイス", + "apiAddress": "API address", + "blocks": "Blocks", + "connection": "接続", + "downSpeed": "受信量", + "example": "例:", + "file": "File", + "files": "ファイル", + "folder": "フォルダ", + "folders": "フォルダ", + "gateway": "ゲートウェイ", + "in": "受信量", + "latency": "レイテンシ", + "loading": "Loading", + "location": "位置", + "name": "名前", + "node": "ノード", + "out": "送信量", + "peer": "ピア", + "peerId": "ピアID", + "id": "ID", + "peers": "ピア", + "pinNoun": "ピン", + "pins": "ピン", + "pinStatus": "ピンの状態", + "publicKey": "公開鍵", + "publicGateway": "公開ゲートウェイ", + "rateIn": "下り通信量", + "rateOut": "上り通信量", + "repo": "Repo", + "size": "サイズ", + "totalIn": "下り通信量(合計)", + "totalOut": "上り通信量(合計)", + "unknown": "不明", + "ui": "UI", + "upSpeed": "送信量", + "revision": "リビジョン" + }, + "tour": { + "back": "戻る", + "close": "閉じる", + "finish": "終了", + "next": "次へ", + "skip": "スキップ", + "tooltip": "Click this button any time for a guided tour on the current page." + }, + "startTourHelper": "Start tour" +} diff --git a/public/locales/ru/files.json b/public/locales/ru/files.json index 101b5d840..5735050ef 100644 --- a/public/locales/ru/files.json +++ b/public/locales/ru/files.json @@ -38,8 +38,8 @@ "titleItem": "{count, plural, one {Удалить {name} объект?} few {Удалить {count} объектов?} many {Удалить {count} объектов?} other {Удалить {count} объектов?}}", "titleFolder": "{count, plural, one {Удалить папку {name}?} few {Удалить {count} папок?} many {Удалить {count} папок?} other {Удалить {count}папок?}}", "titleFile": "{count, plural, one {Удалить файл {name}?} few {Удалить {count} файлов?} many {Удалить {count} файлов?} other {Удалить {count} файлов?}}", - "descriptionItem": "{count, plural, one {Are you sure you want to remove this item? It will no longer appear on the Files screen, and will be permanently removed in the next scheduled cleanup (though copies may exist on other IPFS nodes). This action and cannot be reversed.} other {Are you sure you want to remove these {count} items? They will no longer appear on the Files screen, and will be permanently removed in the next scheduled cleanup (though copies may exist on other IPFS nodes). This action cannot be reversed.}}", - "descriptionFolder": "{count, plural, one {Are you sure you want to remove this folder? It will no longer appear on the Files screen, and will be permanently removed in the next scheduled cleanup (though copies may exist on other IPFS nodes). This action cannot be reversed.} other {Are you sure you want to remove these {count} folders? They will no longer appear on the Files screen, and will be permanently removed in the next scheduled cleanup (though copies may exist on other IPFS nodes). This action cannot be reversed.}}", + "descriptionItem": "{count, plural, one {Вы уверены, что хотите удалить этот элемент? Он больше не будет отображаться на экране \"Файлы\" и будет безвозвратно удален при следующей запланированной очистке (хотя копии могут существовать на других узлах IPFS). Это действие и не может быть отменено.} few {Вы уверены, что хотите удалить эти {count} элементов? Они больше не будет отображаться на экране \"Файлы\" и будут безвозвратно удалены при следующей запланированной очистке (хотя копии могут существовать на других узлах IPFS). Это действие и не может быть отменено.} many {Вы уверены, что хотите удалить эти {count} элементов? Они больше не будет отображаться на экране \"Файлы\" и будут безвозвратно удалены при следующей запланированной очистке (хотя копии могут существовать на других узлах IPFS). Это действие и не может быть отменено.} other {Вы уверены, что хотите удалить эти {count} элементов? Они больше не будет отображаться на экране \"Файлы\" и будут безвозвратно удалены при следующей запланированной очистке (хотя копии могут существовать на других узлах IPFS). Это действие и не может быть отменено.}}", + "descriptionFolder": "{count, plural, one {Вы уверены, что хотите удалить эту папку? Она больше не будет отображаться на экране \"Файлы\" и будет безвозвратно удалена при следующей запланированной очистке (хотя копии могут существовать на других узлах IPFS). Это действие и не может быть отменено.} few {Вы уверены, что хотите удалить эти {count} папок? Они больше не будут отображаться на экране \"Файлы\" и будут безвозвратно удалены при следующей запланированной очистке (хотя копии могут существовать на других узлах IPFS). Это действие и не может быть отменено.} many {Вы уверены, что хотите удалить эти {count} папок? Они больше не будут отображаться на экране \"Файлы\" и будут безвозвратно удалены при следующей запланированной очистке (хотя копии могут существовать на других узлах IPFS). Это действие и не может быть отменено.} other {Вы уверены, что хотите удалить эти {count} папки? Они больше не будут отображаться на экране \"Файлы\" и будут безвозвратно удалены при следующей запланированной очистке (хотя копии могут существовать на других узлах IPFS). Это действие и не может быть отменено.}}", "descriptionFile": "{count, plural, one {Are you sure you want to remove this file? It will no longer appear on the Files screen, and will be permanently removed in the next scheduled cleanup (though copies may exist on other IPFS nodes). This action cannot be reversed.} other {Are you sure you want to remove these {count} files? They will no longer appear on the Files screen, and will be permanently removed in the next scheduled cleanup (though copies may exist on other IPFS nodes). This action cannot be reversed.}}", "checkboxRemoveLocalPin": "Также удалить локальное закрепление (рекомендуется)", "checkboxUnpinFromServices": "Отключить от всех служб закрепления" @@ -97,7 +97,7 @@ "step5": { "title": "Список файлов", "paragraph1": "И наконец, перечень, в котором вы можете найти свои файлы и папки. Перетаскивайте файлы или папки, чтобы добавлять их.", - "paragraph2": "You can share or download files, inspect them in the IPLD Explorer, rename or remove them!", + "paragraph2": "Вы можете делиться файлами или скачивать их, исследовать в IPLD Explorer, переименовывать или удалять!", "paragraph3": "Продвинутая подсказка: перетащите файл с любой другой страницы веб-интерфейса, чтобы добавить его в корень вашего MFS." } }, @@ -120,7 +120,7 @@ "pinningQueue": "Очередь закрепления", "more": "Больше", "files": "Файлы", - "cidNotFileNorDir": "The current link isn't a file, nor a directory. Try to <1>inspect it instead.", + "cidNotFileNorDir": "Текущая ссылка не является ни файлом, ни каталогом. Попробуйте вместо этого <1>исследовать её.", "sortBy": "Сортировка объектов по {name}", "publishModal": { "title": "Опубликовать в IPNS", diff --git a/public/locales/ru/settings.json b/public/locales/ru/settings.json index 54effedbc..a8e11b156 100644 --- a/public/locales/ru/settings.json +++ b/public/locales/ru/settings.json @@ -7,8 +7,8 @@ "showOptions": "Показать настройки", "pinningServices": { "title": "Служба подкрепления", - "description": "Use local pinning when you want to ensure an item on your node is never garbage-collected, even if you remove it from Files. You can also link your accounts with other remote pinning services to automatically or selectively persist files with those providers, enabling you to keep backup copies of your files and/or make them available to others when your local node is offline.", - "noPinRemoteDescription": "Support for third-party remote pinning services is missing. Update your IPFS node to Kubo 0.8.0 or later, and you'll be able to add and configure them here.", + "description": "Используйте локальное закрепление, если вы хотите гарантировать, что элемент на вашем узле никогда не будет удален сборщиком мусора, даже если вы удалите его из файлов. Вы также можете связать свои учетные записи с другими службами удаленного закрепления, чтобы автоматически или выборочно сохранять файлы у этих поставщиков, что позволит вам сохранять резервные копии ваших файлов и/или делать их доступными для других, когда ваш локальный узел отключен.", + "noPinRemoteDescription": "Поддержка сторонних служб удаленного закрепления отсутствует. Обновите свой узел IPFS до версии Kubo 0.8.0 или более поздней, и вы сможете добавлять и настраивать их здесь.", "addAutoUpload": "Включить автозагрузку", "removeAutoUpload": "Выключить автозагрузку" }, @@ -23,7 +23,7 @@ "translationProjectLink": "Присоединитесь к проекту перевода IPFS" }, "apiDescription": "<0>Если в вашем узле настроен <1>собственный адрес API, включая порт, отличный от порта по умолчанию 5001, введите его здесь.", - "publicGatewayDescription": "<0>Choose which <1>public gateway you want to use when generating shareable links.", + "publicGatewayDescription": "<0>Выберите, какой <1>общедоступный шлюз вы хотите использовать при создании общих ссылок.", "cliDescription": "<0>Активируйте эту опцию, чтобы отображать значок \"просмотреть код\" <1> рядом с общими командами IPFS. Нажатие на него открывает модальное окно с кодом заданной команды в командной строке, так чтобы вы могли вставить его в интерфейс командной строки IPFS в вашей консоли.", "cliModal": { "extraNotesJsonConfig": "Если вы произвели изменения настроек в редакторе кода на этой странице, которые вы хотели бы сохранить, нажмите на значок \"скачать\" рядом с кнопкой \"копировать\", чтобы скачать их в виде JSON-файла." @@ -43,7 +43,7 @@ "secretApiKey": "Секретный ключ", "secretApiKeyHowToLink": "Как сгенерировать новый секретный ключ", "autoUpload": "Автозагрузка", - "complianceLabel": "🔍 {nickname} pinning compliance report" + "complianceLabel": "🔍 Отчет сервиса закрепления {nickname} " }, "autoUploadModal": { "title": "Изменить политику загрузки для {name}", @@ -170,7 +170,7 @@ }, "generateKeyModal": { "title": "Генерировать новый ключ IPNS", - "description": "Enter a nickname for this key to generate:" + "description": "Введите псевдоним для генерации этого ключа:" }, "renameKeyModal": { "title": "Переименовать ключ", diff --git a/src/constants/pinning.js b/src/constants/pinning.js index 7d13134fc..128836b85 100644 --- a/src/constants/pinning.js +++ b/src/constants/pinning.js @@ -57,10 +57,15 @@ const pinningServiceTemplates = [ visitServiceUrl: 'https://www.scaleway.com/en/docs/labs/ipfs/api-cli/ipfs-desktop/' } ].map((service) => { - const domain = new URL(service.apiEndpoint).hostname - service.complianceReportUrl = `${complianceReportsHomepage}/${domain}.html` - return service -}).map(service => ({ service, sort: Math.random() })).sort((a, b) => a.sort - b.sort).map(({ service }) => service) + try { + const domain = new URL(service.apiEndpoint).hostname + service.complianceReportUrl = `${complianceReportsHomepage}/${domain}.html` + } catch (e) { + // if apiEndpoint is not a valid URL, don't add complianceReportUrl + // TODO: fix support for template apiEndpoints + } + return { service, sort: Math.random() } +}).sort((a, b) => a.sort - b.sort).map(({ service }) => service) export { complianceReportsHomepage,